ef55560ab731
block autofill while passkey toast active; apply accent color to toast (v2.40.3)
- time
- 2026-05-13 16:43 UTC · 5 months ago
- machine
- koh2
- parent
- b7a8f8c11f80
↓ peach-browser-ef55560a.tar.gzatlas at this save
files changed6 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/content/index.ts+22 −2src/content/passkey-toast/inject.tsx+21 −0src/content/passkey-toast/passkey-toast.css+4 −4manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach",4- "version": "2.40.2",4+ "version": "2.40.3",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.40.2",4+ "version": "2.40.3",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.40.2",3+ "version": "2.40.3",44 "description": "Zero-knowledge password manager",55 "type": "module",66 "scripts": {src/content/index.ts+22 −2
@@ -58,6 +58,10 @@5858 // flow. The VAULT_UNLOCKED handler checks this to skip re-triggering autofill5959 // (the passkey toast handles the next step instead).6060 let passkeySummonActive = false;61+// Set while the passkey approval toast is visible. Prevents handleFieldInteraction62+// from opening the autofill selector alongside it. Cleared by a window message63+// posted by inject.tsx when the toast closes (and by DISMISS_PASSKEY_TOAST).64+let passkeyToastActive = false;6165 function startDismissLock(): void {6266 dismissLock = true;6367 if (dismissLockTimer) clearTimeout(dismissLockTimer);@@ -484,6 +488,9 @@484488 if (!field) return;485489 if (!isVisible(field)) return;486490 491+ // Passkey toast is visible — don't open the credential selector alongside it.492+ if (passkeyToastActive) return;493+487494 // Layer 2: post-dismiss global lock. Catches rapid focus moves between488495 // fields immediately after Escape/click-outside.489496 if (!canOpen()) return;@@ -905,15 +912,19 @@905912 return true;906913 }907914 if (msg?.type === "SHOW_PASSKEY_TOAST") {908- // Dismiss any open autofill selector so it doesn't appear alongside the toast.915+ // Block autofill selector for the lifetime of the toast and dismiss anything open.916+ passkeyToastActive = true;909917 if (currentDismiss) {910918 currentDismiss();911919 currentDismiss = null;912920 currentAnchorField = null;913921 }914- passkeySummonActive = false;915922 return false; // inject.tsx owns the toast and calls sendResponse916923 }924+ if (msg?.type === "DISMISS_PASSKEY_TOAST") {925+ passkeyToastActive = false;926+ return false; // inject.tsx handles the actual dismissal927+ }917928 if (msg?.type === "VAULT_UNLOCKED") {918929 if (passkeySummonActive) {919930 // This unlock was for a pending passkey GET request. Just dismiss the@@ -940,6 +951,15 @@940951 return true;941952 }942953 return true;954+});955+956+// inject.tsx posts this when the passkey toast closes (approve, deny, or timeout)957+// so we know it's safe to allow autofill again.958+window.addEventListener("message", (e: MessageEvent) => {959+ const d = e.data as { source?: string; type?: string } | undefined;960+ if (d?.source === "peach-passkey-toast" && d?.type === "toast-closed") {961+ passkeyToastActive = false;962+ }943963 });944964 945965 // ── Firefox passkey detection bridge (legacy observer path) ─────────────src/content/passkey-toast/inject.tsx+21 −0
@@ -3,6 +3,7 @@33 // ?inline imports the CSS as a string so we can inject it into the shadow root44 // rather than letting Vite/crx inject it into the page document head.55 import styles from './passkey-toast.css?inline';6+import { ACCENT_COLORS } from '../../shared/types';67 78 let currentDispose: (() => void) | null = null;89 let currentRequestId: string | null = null;@@ -23,6 +24,23 @@2324 return shadowRoot!;2425 }2526 27+function applyAccentToShadow(): void {28+ if (!shadowRoot) return;29+ chrome.runtime.sendMessage({ type: 'GET_SETTINGS' }).then((resp: unknown) => {30+ const name = (resp as { ok?: boolean; data?: { accentColor?: string } } | null)?.data?.accentColor;31+ if (!name || !shadowRoot) return;32+ const color = ACCENT_COLORS.find(c => c.name === name);33+ if (!color) return;34+ let el = shadowRoot.querySelector<HTMLStyleElement>('#peach-accent-var');35+ if (!el) {36+ el = document.createElement('style');37+ el.id = 'peach-accent-var';38+ shadowRoot.appendChild(el);39+ }40+ el.textContent = `* { --peach-accent: ${color.hex}; }`;41+ }).catch(() => {});42+}43+2644 export function showPasskeyToast(payload: {2745 site: string;2846 displayName: string;@@ -35,6 +53,7 @@3553 }3654 3755 const root = ensureContainer();56+ applyAccentToShadow();3857 const wrapper = document.createElement('div');3958 root.appendChild(wrapper);4059 @@ -71,6 +90,8 @@7190 wrapper.remove();7291 currentDispose = null;7392 currentRequestId = null;93+ // Tell index.ts the toast is gone so it can re-enable autofill.94+ window.postMessage({ source: 'peach-passkey-toast', type: 'toast-closed' }, '*');7495 }7596 }7697 src/content/passkey-toast/passkey-toast.css+4 −4
@@ -132,7 +132,7 @@132132 133133 .peach-passkey-toast-countdown-bar {134134 height: 100%;135- background: #E8956D;135+ background: var(--peach-accent, #F49C70);136136 border-radius: 1px;137137 transform-origin: left;138138 animation: peach-passkey-countdown linear forwards;@@ -171,7 +171,7 @@171171 172172 .peach-passkey-toast-btn:focus-visible {173173 outline: none;174- box-shadow: 0 0 0 2px #0C0A06, 0 0 0 4px rgba(232, 149, 109, 0.5);174+ box-shadow: 0 0 0 2px #0C0A06, 0 0 0 4px color-mix(in srgb, var(--peach-accent, #F49C70) 50%, transparent);175175 }176176 177177 .peach-passkey-toast-btn:active {@@ -191,12 +191,12 @@191191 }192192 193193 .peach-passkey-toast-btn--signin {194- background: #E8956D;194+ background: var(--peach-accent, #F49C70);195195 color: rgba(0, 0, 0, 0.92);196196 font-weight: 500;197197 box-shadow:198198 0 1px 0 rgba(255, 255, 255, 0.08) inset,199- 0 3px 16px rgba(232, 149, 109, 0.16);199+ 0 3px 16px color-mix(in srgb, var(--peach-accent, #F49C70) 16%, transparent);200200 }201201 202202 .peach-passkey-toast-btn--signin:hover {