fc721b3898a8

show the topbar sync button unconditionally, and shrink the bird stage and QR on the invitation screen so the bird is no longer clipped to its legs (v4.1.13)

time
2026-07-26 15:07 UTC · 3 months ago
machine
koh2
agent
claude-opus-5
session
sync UX and scanner crash
parent
33473d579a29
6 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/popup/App.tsx+4 −10src/popup/styles/popup.css+18 −0src/popup/views/PairDevice.tsx+1 −1
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "4.1.12",4+  "version": "4.1.13",55   "description": "Zero-knowledge password manager",66   "browser_specific_settings": {77     "gecko": {

view file

manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "4.1.12",4+  "version": "4.1.13",55   "description": "Zero-knowledge password manager",66   "action": {77     "default_popup": "src/popup/index.html",

view file

package.json+1 −1
@@ -1,6 +1,6 @@11 {22   "name": "peach",3-  "version": "4.1.12",3+  "version": "4.1.13",44   "description": "Zero-knowledge password manager",55   "license": "GPL-3.0-only",66   "type": "module",

view file

src/popup/App.tsx+4 −10
@@ -216,9 +216,9 @@216216   const [editBackView, setEditBackView] = createSignal<View>("entry");217217   const [settingsExiting, setSettingsExiting] = createSignal(false);218218   const [showNotes, setShowNotes] = createSignal(false);219-  // Topbar sync affordance. `syncPaired` gates the button's existence — with no220-  // paired device there is nothing to sync and the icon would be a dead control.221-  const [syncPaired, setSyncPaired] = createSignal(false);219+  // Topbar sync affordance. Always present: gating it on having a paired device220+  // meant it never appeared for the person trying to set pairing up, which is221+  // exactly when you reach for it.222222   const [syncBusy, setSyncBusy] = createSignal(false);223223   const [syncFlash, setSyncFlash] = createSignal<"ok" | "error" | null>(null);224224   const [openNoteId, setOpenNoteId] = createSignal<string | undefined>(undefined);@@ -390,10 +390,6 @@390390       });391391       // UI-1 / HV-1b: surface any remote-mutation alerts the sync merge queued.392392       void loadSyncAlerts();393-      void sendMessage({ type: "LIST_PAIRED_DEVICES" }).then((res) => {394-        const devices = (res as { ok: boolean; data?: unknown }).data;395-        setSyncPaired(Array.isArray(devices) && devices.length > 0);396-      });397393     }398394 399395     // If the user created a vault but hasn't yet confirmed their recovery@@ -1451,8 +1447,7 @@14511447                     <line x1="4" y1="10" x2="7" y2="10" />14521448                   </svg>14531449                 </button>1454-                <Show when={syncPaired()}>1455-                  <button1450+                <button14561451                     class="peach-btn peach-btn--ghost peach-btn--sm peach-icon-btn peach-sync-btn"14571452                     classList={{14581453                       "is-syncing": syncBusy(),@@ -1471,7 +1466,6 @@14711466                       <path d="M11.4 13v-2.4H9" />14721467                     </svg>14731468                   </button>1474-                </Show>14751469                 <button14761470                   class="peach-btn peach-btn--ghost peach-btn--sm peach-icon-btn"14771471                   onClick={() => setView("settings")}

view file

src/popup/styles/popup.css+18 −0
@@ -9557,6 +9557,24 @@95579557 .peach-pair-bird-slot-desktop { left: 28px; }95589558 .peach-pair-bird-slot-mobile { right: 28px; }95599559 9560+/* The QR screen is the tallest in the flow: a 180px stage plus headline, sub,9561+   QR and action overflows the popup, and the stage is what gets clipped — you9562+   saw bird legs and nothing else. Shrink the stage and the birds with it here9563+   only, so the birds stay whole and the QR stays comfortably above the fold.9564+   Uses the individual `scale` property rather than `transform`, which the9565+   mobile bird's hop animation already owns. */9566+.peach-adoption-source[data-phase="invitation"] .peach-pair-stage {9567+  height: 108px;9568+  margin: 8px 0 6px;9569+}9570+.peach-adoption-source[data-phase="invitation"] .peach-pair-bird-slot {9571+  scale: 0.62;9572+  transform-origin: center bottom;9573+}9574+.peach-adoption-source[data-phase="invitation"] .peach-pair-stage::after {9575+  bottom: 20px;9576+}9577+95609578 /* Mobile bird hops in from the right when handshake begins */95619579 .peach-pair-bird-slot-mobile {95629580   opacity: 1;

view file

src/popup/views/PairDevice.tsx+1 −1
@@ -453,7 +453,7 @@453453             Connecting via secure relay — works anywhere. The QR contains only454454             the relay address and a single-use random token.455455           </div>456-          <PairingQrCode value={invitation()} size={224} />456+          <PairingQrCode value={invitation()} size={188} />457457           <div class="peach-pair-action">458458             <button459459               class="peach-btn peach-btn-ghost"

view file