From 7b26a51f9bc10e8ec6447d7cf153778a338c6bff Mon Sep 17 00:00:00 2001 From: Nguyen Ngo Date: Sun, 19 Apr 2026 18:49:59 -0400 Subject: [PATCH] 04/19 Update extension: add item prompt exist until user clicks the button, fix All relevant tab content --- extension/background.js | 4 +++- extension/popup/popup.js | 29 ++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/extension/background.js b/extension/background.js index 4b643e2..076e5f6 100644 --- a/extension/background.js +++ b/extension/background.js @@ -92,7 +92,9 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { // Content script detected credentials on form submit → store for save-prompt. if (msg.type === "SAVE_CREDENTIALS") { - chrome.storage.session.set({ pending_save: msg.data }); + // Store in local storage so the prompt survives service worker restarts + // and is guaranteed to be present when the user next opens the popup. + chrome.storage.local.set({ pending_save: msg.data }); sendResponse({ ok: true }); return false; } diff --git a/extension/popup/popup.js b/extension/popup/popup.js index fdca0a5..34cff4a 100644 --- a/extension/popup/popup.js +++ b/extension/popup/popup.js @@ -438,16 +438,8 @@ function getTabItems() { } if (_activeTab === "relevant") { - // Show matching items first, then others (only if there are matches or no query) - const matches = items.filter(isMatch); - const rest = items.filter((i) => !isMatch(i)); - // If we have matches, show matches first; otherwise fall back to all - items = matches.length ? [...matches, ...rest] : items; - // Sort matched first by name, rest by name - items = [ - ...matches.sort((a, b) => a.name.localeCompare(b.name)), - ...rest.sort((a, b) => a.name.localeCompare(b.name)), - ]; + // Show ONLY items that match the current domain, sorted by name. + items = items.filter(isMatch).sort((a, b) => a.name.localeCompare(b.name)); } else if (_activeTab === "recents") { items = [...items] .sort( @@ -470,6 +462,14 @@ function renderList() { if (!items.length) { listEl.innerHTML = ""; + if (_activeTab === "relevant") { + const host = currentHostname(); + emptyEl.textContent = host + ? `No saved passwords for ${host}.` + : "No items match this page."; + } else { + emptyEl.textContent = "No items found."; + } emptyEl.classList.remove("hidden"); return; } @@ -585,9 +585,12 @@ function initTabs() { * Show the save-prompt overlay. It is a blocking modal — no backdrop click, * no ✕ button — so the user MUST click "Save" or "Not now". * Called every time the popup opens while a pending_save is stored. + * + * pending_save is stored in chrome.storage.local (not session) so it survives + * service worker restarts and is reliably present when the popup re-opens. */ async function checkPendingSave() { - const { pending_save } = await chrome.storage.session.get("pending_save"); + const { pending_save } = await chrome.storage.local.get("pending_save"); if (!pending_save) return; // Populate fields. @@ -611,7 +614,7 @@ async function checkPendingSave() { pending_save.siteName, ); await saveCredential(pending_save); - await chrome.storage.session.remove("pending_save"); + await chrome.storage.local.remove("pending_save"); }; $("btn-save-no").onclick = async () => { $("save-prompt-overlay").classList.add("hidden"); @@ -619,7 +622,7 @@ async function checkPendingSave() { "[PassKeeper] User dismissed save prompt for", pending_save.siteName, ); - await chrome.storage.session.remove("pending_save"); + await chrome.storage.local.remove("pending_save"); }; }