| index d4b278c..aafce43 100644 |
| --- a/home/web/static/home.js |
| +++ b/home/web/static/home.js |
| @@ -2061,6 +2061,11 @@ function showVault() { |
| box.append(emptyLine(archived.length |
| ? "All your spaces are archived β open the archive to bring one back." |
| : "None (yet). Creating is invite-only for now.")); |
| + // Truly empty + signed in through an anchor: this may be the wrong-door |
| + // landing β their spaces could live under an older passkey account. |
| + const m = sessionMethod(); |
| + if (!archived.length && m && m !== "passkey" && window.PublicKeyCredential) |
| + box.append(bringOverLine()); |
| } else { |
| const servers = query ? filterServers(active, query) : active; |
| if (!servers.length) { |
| @@ -2205,6 +2210,40 @@ function emptyLine(text) { |
| return p; |
| } |
| |
| +// Which method is holding THIS session up β the persisted session records it; |
| +// the last-signin marker covers a tab-only (unpersisted) session. "" when |
| +// unknowable. |
| +function sessionMethod() { |
| + const s = persistedSession(); |
| + if (s && s.method) return s.method; |
| + try { return localStorage.getItem("home_last_signin") || ""; } catch { return ""; } |
| +} |
| + |
| +// The wrong-door landing: an Apple/email sign-in that resolves a brand-new |
| +// account shows an empty list β but this person's spaces may live under the |
| +// passkey they used before anchors existed. Offer the bridge in place: the |
| +// ordinary passkey door, run from the signed-in view. signIn() touches no |
| +// state until the ceremony succeeds, so cancelling leaves this session |
| +// exactly as it was; success swaps to the passkey account, where Sign-in |
| +// options β Add pulls this anchor over (the combine flow). |
| +function bringOverLine() { |
| + const p = document.createElement("p"); |
| + p.className = "empty"; |
| + const b = document.createElement("button"); |
| + b.type = "button"; |
| + b.className = "passkey-link"; |
| + b.textContent = "Sign in with your passkey"; |
| + b.addEventListener("click", () => { |
| + b.disabled = true; |
| + vaultStatus("Confirming itβs youβ¦", "busy"); |
| + signIn().then(() => vaultStatus(""), () => { |
| + vaultStatus("That passkey didnβt confirm β nothing has changed.", "error"); |
| + }).finally(() => { b.disabled = false; setSignedOutBusy(false); setStatus(""); }); |
| + }); |
| + p.append("Already have spaces? ", b, " to bring them over."); |
| + return p; |
| +} |
| + |
| function sectionHeading(text) { |
| const h = document.createElement("div"); |
| h.className = "spaces-head"; |