From 802c40e6ac436ea93b776f183142cbcabe74f0a5 Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Sat, 8 Aug 2026 17:13:11 -0400 Subject: [PATCH] feat: keep the current login through the switch-account form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch account no longer signs out up front — it just opens the sign-in panel, and the worker retires the old session once the replacement sign-in completes. Abandoning the switch leaves the session as it was. The header Sign in button now appears alongside the account chip while the panel is open, so the form keeps its one submit button, and a profile refresh landing mid-switch no longer closes the panel. Co-Authored-By: Claude Fable 5 --- README.md | 5 ++++- src/popup/popup.ts | 25 +++++++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 26fe77b..a0ac9eb 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,10 @@ subscription records and nothing else. Account controls live in the popup header: a Sign in button when signed out, and your avatar and handle when signed in, opening a menu with Switch account and Sign out. The Sign in button expands into the handle form and then -submits it — it is the form's only button. A session that ends on its own +submits it — it is the form's only button. Switch account opens that same +form without signing you out: the current login stays valid until the +replacement sign-in completes, and only then is it revoked. Abandoning the +switch leaves you signed in as before. A session that ends on its own (expired or remotely revoked refresh token) is flagged once in that panel, so being signed out always has an explanation. diff --git a/src/popup/popup.ts b/src/popup/popup.ts index d75c461..f45b4d7 100644 --- a/src/popup/popup.ts +++ b/src/popup/popup.ts @@ -117,13 +117,15 @@ async function loadState(refresh: boolean) { } function renderAccount() { - $('signin-open').hidden = !!session $('account-btn').hidden = !session if (!session) { $('account-menu').hidden = true + $('signin-open').hidden = false return } - setSigninPanel(false) + // Keep the panel as it is: a profile refresh landing mid-switch must not + // close the form under the user. + setSigninPanel(!$('signin-panel').hidden) $('account-handle').textContent = `@${session.handle ?? session.did}` const img = $('account-avatar') const url = session.avatarUrl @@ -142,12 +144,16 @@ function renderAccount() { /** * The header Sign in button is the panel's only button: it expands into the * handle form, and once open it submits it. Everything that hides the panel - * must go through here so the button's state stays truthful. + * must go through here so the button's state stays truthful. While signed in + * the button appears only with the panel (the switch-account flow), so the + * form always has its submit button. */ function setSigninPanel(open: boolean) { + const opening = open && $('signin-panel').hidden $('signin-panel').hidden = !open + $('signin-open').hidden = !!session && !open $('signin-open').setAttribute('aria-expanded', String(open)) - if (open) $('handle-input').focus() + if (opening) $('handle-input').focus() } function openSigninPanel() { @@ -447,13 +453,12 @@ $('signin-form').addEventListener('submit', async (e) => { }) wireTypeaheadSubmit($('handle-input'), $('signin-form')) -$('switch-account').addEventListener('click', async (e) => { +// Just a shortcut into the sign-in form: the current login stays usable, and +// the worker revokes it only once the replacement sign-in completes +// (src/signin.ts). Closing the popup or the consent window changes nothing. +$('switch-account').addEventListener('click', (e) => { e.stopPropagation() - await invalidateSubsCache() - await signOut() - session = undefined - renderAccount() - render() + $('account-menu').hidden = true openSigninPanel() }) -- 2.54.0