diff options
| author | Adam Soltys <[email protected]> | 2026-09-14 19:14:38 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-14 19:14:38 -0700 |
| commit | 4409629ab28372def6afb07c2fb1e124a58ab171 (patch) | |
| tree | 65474cfb28b7ce8fd1602e141aac01cacef52d8a /src/app.js | |
| parent | de9efec9205f5faa0245d1d0182e87931f2d26c2 (diff) | |
| download | coinosv3-4409629ab28372def6afb07c2fb1e124a58ab171.tar.gz coinosv3-4409629ab28372def6afb07c2fb1e124a58ab171.zip | |
Logging out leaves one identity, not everyone on the device.
With several identities signed in, the profile's Log out now signs out
only the current one: its accounts leave the session, directory, cache
and vault, the others stay put, and the next identity takes the screen.
The confirmation names who is leaving and says whether they can sign
straight back in (a nostr login) or need their recovery phrase (a bare
seed). Logging out of every account is a second, explicit button. Alone
on the device, Log out is unchanged.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to 'src/app.js')
| -rw-r--r-- | src/app.js | 35 |
1 files changed, 31 insertions, 4 deletions
@@ -1495,14 +1495,17 @@ function identityPkOf(a) { // Both are read from the account itself; the key remembered on the record // (saveDirectory) and in the durable directory by xpub is only the fallback, // for a watch-only entry whose seed isn't here to ask. +// One key per person: a seed's Spending and Savings accounts share it. +const seedKeyOf = (a) => a.type === 'watch' ? 'w:' + a.xpub + : a.mnemonic ? 'm:' + a.mnemonic + '\n' + (a.passphrase || '') + '\n' + (a.deriveIndex || 0) + : 'x:' + (a.xprv || a.xpub || a.id); + function identities() { const pkOf = identityPkOf; const bySeed = new Map(); for (const a of accounts) { if (a.provisional) continue; - const key = a.type === 'watch' ? 'w:' + a.xpub - : a.mnemonic ? 'm:' + a.mnemonic + '\n' + (a.passphrase || '') + '\n' + (a.deriveIndex || 0) - : 'x:' + (a.xprv || a.xpub || a.id); + const key = seedKeyOf(a); const active = a.id === activeId; const pk = pkOf(a); const cur = bySeed.get(key); @@ -1527,6 +1530,30 @@ function clearFeatureNav() { ui.chatOpen = false; ui.userSearch = null; ui.noteThread = null; ui.zapSetup = null; } +// Sign out of the CURRENT identity only. "Log out" locks every account on +// the device, which is the wrong size when two people (or two of your own +// keys) are signed in and just one should leave. This removes that +// identity's accounts — session, directory, cache, vault — and leaves the +// others exactly as they were, landing on the next one. A nostr login can +// sign straight back in (its seed lives on the relays, encrypted to its +// key); a bare seed wallet needs its recovery phrase, and the confirmation +// says which. +function signOutIdentity() { + const me = activeAccount(); + if (!me) return; + const key = seedKeyOf(me); + const mine = accounts.filter((a) => seedKeyOf(a) === key).map((a) => a.id); + clearFeatureNav(); + // the active one last: wiping it is what hands off to the next identity + for (const id of mine.filter((id) => id !== me.id)) wipeAccount(id); + wipeAccount(me.id); + if (!activeAccount()) { ui.screen = 'unlock'; ui.unlockTab = 'create'; ui.onb = { step: 'welcome' }; } + render(); +} +// Whether the current identity can come back without a recovery phrase: +// a nostr login (extension, bunker, passkey, Google) re-derives its wallet. +const identityRecoverable = () => !!loginPkOf(activeAccount() || {}); + // Switch to another identity already signed in on this device: the wallet // it opens lands on its own history, out of any profile or chat the previous // identity had open. @@ -5282,7 +5309,7 @@ const ctx = { // this runs — wipe now and land on the front door. // identity switching lives on the profile page (the Accounts screen is // about Spending/Savings faces, not who you are) - signInAnother, identities, switchIdentity, + signInAnother, identities, switchIdentity, signOutIdentity, identityRecoverable, logoutForget: () => { ui.profilePk = null; ui.profEdit = null; ui.profEditFilled = false; ui.chatOpen = false; ui.pubProf = null; |
