49c3bcb72e5c
entry URL editor: + add current site button uses active tab URL, fills primary if empty else appends to additional URLs, dedupes (v2.16.4)
- time
- 2026-05-01 03:27 UTC · 5 months ago
- machine
- koh2
- parent
- 17914c240bb4
↓ peach-browser-49c3bcb7.tar.gzatlas at this save
files changed5 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/popup/App.tsx+7 −0src/popup/views/Entry.tsx+38 −0manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.16.3",4+ "version": "2.16.4",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.16.3",4+ "version": "2.16.4",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "2.16.3",3+ "version": "2.16.4",44 "description": "Zero-knowledge password manager",55 "type": "module",66 "scripts": {src/popup/App.tsx+7 −0
@@ -148,6 +148,7 @@148148 const [restoreView, setRestoreView] = createSignal<"file" | null>(null);149149 const [pendingPasskey, setPendingPasskey] = createSignal<PendingPasskeyRequest | null>(null);150150 const [currentTabDomain, setCurrentTabDomain] = createSignal<string>("");151+ const [currentTabUrl, setCurrentTabUrl] = createSignal<string>("");151152 // Cached Pro status — synchronous for render paths. Background's152153 // GET_LICENSE is async, but render-time reads of isPro() must not block.153154 // Refreshed at boot, after activate/deactivate, and whenever the popup@@ -690,8 +691,13 @@690691 const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });691692 const url = tab?.url ?? tab?.pendingUrl ?? "";692693 setCurrentTabDomain(url ? (extractDomain(url) ?? "") : "");694+ // Skip extension/internal URLs — adding chrome://, about:, or695+ // chrome-extension:// to a vault entry is never what the user wants.696+ const isWebUrl = /^https?:\/\//i.test(url);697+ setCurrentTabUrl(isWebUrl ? url : "");693698 } catch {694699 setCurrentTabDomain("");700+ setCurrentTabUrl("");695701 }696702 }697703 @@ -1221,6 +1227,7 @@12211227 <div class="peach-content-frame" data-content-phase={contentPhase()} classList={{ navigating: contentTransitioning() }}>12221228 <EntryView12231229 entry={selectedEntry()}1230+ currentTabUrl={currentTabUrl()}12241231 onDelete={handleDelete}12251232 onFieldSaved={() => void loadEntries()}12261233 onEscape={() => { setView("list"); }}src/popup/views/Entry.tsx+38 −0
@@ -14,6 +14,12 @@1414 1515 interface EntryProps {1616 entry: VaultEntry | null;17+ /**18+ * Current active tab's full URL (https only). Empty string when unavailable19+ * — Capacitor, an extension page, or a chrome:///about: URL. The URL20+ * editor uses this to render an "add current site" shortcut.21+ */22+ currentTabUrl?: string;1723 onDelete: () => void;1824 /** Called after any inline save so App can reload entries */1925 onFieldSaved: () => void | Promise<void>;@@ -157,6 +163,26 @@157163 }158164 }159165 166+ // Compare URLs by string after trim — vault.ts has its own canonicalisation167+ // when saving, so the dedupe here is a UX-level "don't show the button if168+ // we'd just add a duplicate" rather than a security check.169+ function urlMatchesAny(candidate: string, primary: string, others: string[]): boolean {170+ const c = candidate.trim();171+ if (!c) return true;172+ if (primary.trim() === c) return true;173+ return others.some((u) => u.trim() === c);174+ }175+176+ function addCurrentSite(url: string) {177+ if (!url) return;178+ if (!draft().trim()) {179+ setDraft(url);180+ return;181+ }182+ if (urlMatchesAny(url, draft(), additionalUrlsDraft())) return;183+ setAdditionalUrlsDraft((arr) => [...arr, url]);184+ }185+160186 async function saveField() {161187 const field = editingField();162188 const entry = props.entry;@@ -563,6 +589,18 @@563589 >564590 + add another url565591 </button>592+ <Show when={props.currentTabUrl && !urlMatchesAny(props.currentTabUrl!, draft(), additionalUrlsDraft())}>593+ <button594+ class="peach-add-field-link peach-additional-urls-add peach-additional-urls-add-current"595+ type="button"596+ title={props.currentTabUrl}597+ onMouseDown={(e) => e.preventDefault()}598+ onClick={() => addCurrentSite(props.currentTabUrl!)}599+ disabled={saving()}600+ >601+ + add current site602+ </button>603+ </Show>566604 </div>567605 </div>568606 </Show>