diff options
| author | Adam Soltys <[email protected]> | 2026-09-10 14:00:36 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-10 14:00:36 -0700 |
| commit | 521cccbb60546190a91ae126164a456cc3b749bd (patch) | |
| tree | a01a1a9b399354fd340185c3d54e6f54ea890d60 /src/app.js | |
| parent | d61b2be95db793d3d8d43b2158f5d514207cab09 (diff) | |
| download | coinosv3-521cccbb60546190a91ae126164a456cc3b749bd.tar.gz coinosv3-521cccbb60546190a91ae126164a456cc3b749bd.zip | |
Identity switching moves to the profile page, with faces.
The Accounts screen is about a seed's Spending/Savings faces — its rows say
nothing about WHO each pair belongs to, so a "Sign into another account"
button there was the wrong door. It's gone from there. On your own profile,
"Sign into another account" now opens a switcher: every identity already
signed in on this device as an avatar + name row (one per seed, wearing the
nostr key its header avatar shows — the login key when there is one, else
the seed's own; remembered on the account and in the durable directory by
xpub, so vault-restored accounts have a face too), tap to switch with nothing
logged out, plus "Sign into a new account" for the additive sign-in doors.
With no other identity on the device the button goes straight to those doors.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01URmfo8VimCNkw6Y7JndYrv
Diffstat (limited to 'src/app.js')
| -rw-r--r-- | src/app.js | 53 |
1 files changed, 45 insertions, 8 deletions
@@ -1326,6 +1326,48 @@ function signInAnother() { ui.profilePk = null; ui.profEdit = null; ui.profEditFilled = false; ui.chatOpen = false; render(); } + +// The identities on this device — one per seed (a seed's Spending and +// Savings faces are the same person), each with the nostr key its header +// avatar wears: the nostr login when there is one, else the seed's own key. +// A key is remembered on the account when it's active (saveDirectory) and in +// the durable directory by xpub, so accounts restored from the vault still +// show a face; one never opened on this device has no key yet and falls back +// to its label. +function identities() { + let dir = []; + try { dir = JSON.parse(localStorage.getItem(WATCH_KEY) || '[]'); } catch {} + const dirPk = (a) => (a.xpub && (dir.find((d) => d.xpub === a.xpub) || {}).nostrPk) || null; + 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 active = a.id === activeId; + const pk = a.nostrPk || dirPk(a); + const cur = bySeed.get(key); + if (!cur) bySeed.set(key, { id: a.id, pk, active, label: seedName(a), network: a.network, watch: a.type === 'watch' }); + else { + if (active) { cur.id = a.id; cur.active = true; } + if (!cur.pk && pk) cur.pk = pk; + } + } + const out = [...bySeed.values()]; + const me = out.find((x) => x.active); + if (me) me.pk = ctx.shownPubkey() || me.pk; + return out; +} + +// 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. +function switchIdentity(id) { + const acc = accounts.find((a) => a.id === id); + if (!acc) return; + ui.profilePk = null; ui.profEdit = null; ui.profEditFilled = false; ui.chatOpen = false; + switchToView(acc.id, viewsOf(acc)[0]); +} // The working set of wallets you can switch between. Full (seed-bearing) // accounts live only in sessionStorage — ephemeral, wiped when the browser // closes (no seed on disk by default). Watch-only accounts hold just an xpub, @@ -2584,13 +2626,6 @@ function accountsScreen() { })) ), h('button', { class: 'btn-block', onClick: () => { ui.addWallet = { kind: 'spending', from: 'new' }; render(); } }, t('addWallet')), - // Sign into a DIFFERENT identity (Nostr signer, passkey, Google) without - // logging out: the unlock screen carries the sign-in doors, and enterWallet - // ADDS the account alongside the current ones (fromWallet keeps them + a - // Back). Switching between them afterwards is just tapping a row above. - h('div', { class: 'col', style: 'gap:4px' }, - h('button', { class: 'btn-ghost btn-block', onClick: signInAnother }, t('signInAnother')), - h('div', { class: 'small faint', style: 'padding:0 2px' }, t('signInAnotherNote'))), hasVault() ? h('button', { class: 'btn-ghost btn-block', onClick: startChangePw }, t('changePassword')) : null, h('button', { class: 'btn-ghost btn-block', onClick: () => { ui.confirmClear = true; render(); } }, t('clearAll')) ), @@ -4888,7 +4923,9 @@ const ctx = { // Routes through the Delete-all warning — never a single tap. // The popup has already shown the delete-everything warning by the time // this runs — wipe now and land on the front door. - signInAnother, + // identity switching lives on the profile page (the Accounts screen is + // about Spending/Savings faces, not who you are) + signInAnother, identities, switchIdentity, logoutForget: () => { ui.profilePk = null; ui.profEdit = null; ui.profEditFilled = false; ui.chatOpen = false; ui.pubProf = null; |
