[ui] #36: auto-open the unlock-saved-key flow from storage when an nsec session is locked

Follow-up to the locked-nsec detection: clicking "Unlock Storage" on a locked
persisted-nsec session (no in-memory signer after a page reload) now auto-opens the
login modal straight to its existing unlock-saved-key (passphrase) flow, so the user
re-unlocks in one step instead of hunting for the Login menu. Once unlocked, the
signer is active app-wide and re-opening the storage pane auto-unlocks.

- applicationBootstrap: add a side-effect-free openLoginModal service to
  profileModalServices (app.loginModalController.openModal — no add-account callback;
  idempotently ensures the modal is initialized first).
- ProfileStorageController: reportLockedNsecSession({ autoOpenLogin }) opens the modal
  only from the user-initiated unlock click, never from the passive pane render (no
  surprise popups).
- Tests extended to 8 (auto-open fires on click; stays closed on passive render).

Build + lint clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-30 09:35:40 -04:00
1 parent a669040740
commit 35bb1bc576
4 files changed
+77 -9

No files matched your search

+18 -1
View File
@@ -20,6 +20,7 @@ const OTHER_PUBKEY = "b".repeat(64);
function makeController({ meta } = {}) {
const shownErrors = [];
const loginOpens = [];
const mainController = {
normalizeHexPubkey: (value) =>
typeof value === "string" ? value.trim().toLowerCase() : "",
@@ -29,10 +30,14 @@ function makeController({ meta } = {}) {
nostrClient: {
getStoredSessionActorMetadata: () => meta,
},
openLoginModal: (options) => {
loginOpens.push(options ?? null);
return true;
},
},
};
const controller = new ProfileStorageController(mainController);
return { controller, shownErrors };
return { controller, shownErrors, loginOpens };
}
const persistedNsecMeta = {
@@ -81,6 +86,18 @@ test("reporting the locked session shows the actionable re-unlock message, not a
assert.doesNotMatch(msg, /no active signer/i);
});
test("autoOpenLogin opens the login modal's unlock flow (one-click re-unlock)", () => {
const { controller, loginOpens } = makeController({ meta: persistedNsecMeta });
controller.reportLockedNsecSession({ autoOpenLogin: true });
assert.equal(loginOpens.length, 1, "should open the login modal exactly once");
});
test("the passive path does NOT auto-open the login modal (no surprise popups)", () => {
const { controller, loginOpens } = makeController({ meta: persistedNsecMeta });
controller.reportLockedNsecSession();
assert.equal(loginOpens.length, 0, "default (passive) report must not open a modal");
});
test("the new error code maps to a saved-key/passphrase message", () => {
const { controller } = makeController({ meta: persistedNsecMeta });
const msg = controller.getStorageUnlockFailureMessage({