af0831a8ab00

sync info sheet: SyncInfoSheet wired into Settings renderSync, hasPaired flag loaded and PAIRING_COMPLETED tracked, setHasPaired called on pairing completion in SyncPairing, bump 2.35.8 → 2.35.9

time
2026-05-09 01:57 UTC · 5 months ago
machine
koh2
parent
a3b65b7baf9c
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/popup/views/Settings.tsx+34 −4src/popup/views/SyncPairing.tsx+2 −0
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach",4-  "version": "2.35.8",4+  "version": "2.35.9",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",4-  "version": "2.35.8",4+  "version": "2.35.9",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": "2.35.8",3+  "version": "2.35.9",44   "description": "Zero-knowledge password manager",55   "type": "module",66   "scripts": {

view file

src/popup/views/Settings.tsx+34 −4
@@ -1,4 +1,4 @@1-import { createSignal, For, Match, onMount, Show, Switch } from "solid-js";1+import { createEffect, createSignal, For, Match, onMount, Show, Switch } from "solid-js";22 import { sendMessage } from "../App";33 import { PeachMark } from "../components/PeachMark";44 import { LockRuneCanvas } from "../components/LockRuneCanvas";@@ -22,6 +22,8 @@2222   type ShortcutAction,2323 } from "../../shared/shortcuts";2424 import { isNativePlatform, nativePlugin } from "../../shared/native";25+import { getHasPaired } from "../../background/sync-storage";26+import { SyncInfoSheet } from "../components/SyncInfoSheet";2527 2628 interface LicenseInfo {2729   valid: boolean;@@ -123,6 +125,8 @@123125   // immediately without waiting for a sync round-trip.124126   const [syncProStatus, setSyncProStatus] = createSignal(false);125127   const isPro = () => props.isPro ?? syncProStatus();128+  const [hasPaired, setHasPairedLocal] = createSignal(false);129+  const [showSyncInfoSheet, setShowSyncInfoSheet] = createSignal(false);126130   const [syncingNow, setSyncingNow] = createSignal(false);127131   const [biometricSupported, setBiometricSupported] = createSignal(false);128132   const [biometricStored, setBiometricStored] = createSignal(false);@@ -229,15 +233,18 @@229233   const [fbResult, setFbResult] = createSignal<"success" | "error" | null>(null);230234 231235   onMount(async () => {232-    const [licenseRes, syncRes, passkeyRes, duressRes, settingsRes, keyRes] = await Promise.all([236+    const [licenseRes, syncRes, passkeyRes, duressRes, settingsRes, keyRes, pairedFlag] = await Promise.all([233237       sendMessage({ type: "GET_LICENSE" }),234238       sendMessage({ type: "GET_SYNC_STATE" }),235239       sendMessage({ type: "GET_PASSKEY_PROVIDER_STATE" }),236240       sendMessage({ type: "IS_DURESS_ENABLED" }),237241       sendMessage({ type: "GET_SETTINGS" }),238242       sendMessage({ type: "GET_LICENSE_KEY" }),243+      getHasPaired(),239244     ]);240245 246+    setHasPairedLocal(pairedFlag);247+241248     // Vault history loads in the background — the Vault sub-view picks it up242249     // when the user navigates in. Loading it lazily keeps Settings boot fast.243250     void loadVaultHistory();@@ -300,6 +307,9 @@300307         setLastSyncAt(msg.lastSyncAt);301308         setSyncProStatus(msg.isPro ?? false);302309       }310+      if (msg.type === "PAIRING_COMPLETED") {311+        setHasPairedLocal(true);312+      }303313     });304314 305315     if (isNativePlatform()) {@@ -318,6 +328,14 @@318328     }319329   });320330 331+  createEffect(() => {332+    if (activeSection() === "sync") {333+      setShowSyncInfoSheet(!isPro() && !hasPaired());334+    } else {335+      setShowSyncInfoSheet(false);336+    }337+  });338+321339   async function handleEnableBiometrics() {322340     setBiometricBusy(true);323341     setBiometricError(null);@@ -1298,7 +1316,18 @@12981316 12991317   function renderSync() {13001318     return (1301-      <div class="peach-settings-body">1319+      <>1320+        <Show when={showSyncInfoSheet()}>1321+          <SyncInfoSheet1322+            onGotIt={() => setShowSyncInfoSheet(false)}1323+            onLearnPro={() => {1324+              setShowSyncInfoSheet(false);1325+              setActiveSection("license");1326+            }}1327+          />1328+        </Show>1329+1330+        <div class="peach-settings-body">13021331         <div class="peach-settings-group">13031332           <p class="peach-sync-network-note">13041333             Sync works on your home and trusted networks. Some public or@@ -1346,7 +1375,7 @@13461375           <Show13471376             when={isPro()}13481377             fallback={1349-              <Show when={pairedDevices().length > 0}>1378+              <Show when={hasPaired()}>13501379                 <div class="peach-sync-pro-hint">13511380                   <p class="peach-settings-hint">13521381                     Upgrade to Pro for automatic background sync across all your devices.@@ -1474,6 +1503,7 @@14741503           </Show>14751504         </div>14761505       </div>1506+      </>14771507     );14781508   }14791509 

view file

src/popup/views/SyncPairing.tsx+2 −0
@@ -2,6 +2,7 @@22 import { createSignal, onCleanup, onMount, Show } from "solid-js";33 import { sendMessage } from "../App";44 import type { PairedDevice } from "../../shared/sync-types";5+import { setHasPaired } from "../../background/sync-storage";56 67 interface SyncPairingProps {78   onClose: () => void;@@ -48,6 +49,7 @@4849       setExpiresAt(null);4950       setTimeLeft(0);5051       setPairedDevice(device);52+      void setHasPaired();5153       props.onPaired(device);5254     }5355   }

view file