24d24af0eefd

add peachscript tile to onboarding restore picker as primary option; add initialView prop to ImportView so callers can deep-link into a specific subview; bump 2.7.2

time
2026-04-28 04:07 UTC · 6 months ago
machine
koh2
parent
bce5897d91f7
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/popup/views/Import.tsx+8 −3src/popup/views/Lock.tsx+26 −2
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach",4-  "version": "2.7.1",4+  "version": "2.7.2",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.7.1",4+  "version": "2.7.2",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.7.1",3+  "version": "2.7.2",44   "description": "Zero-knowledge password manager",55   "type": "module",66   "scripts": {

view file

src/popup/views/Import.tsx+8 −3
@@ -22,14 +22,19 @@2222 interface ImportProps {2323   mode?: "existing" | "onboarding";2424   replacesExistingVault?: boolean;25+  /** Skip the menu and open straight into a specific subview. */26+  initialView?: ImportSubview;2527   onBack: () => void;2628   onImport: () => void | Promise<void>;2729 }2830 2931 export function ImportView(props: ImportProps) {30-  const [view, setView] = createSignal<ImportSubview>("menu");32+  const [view, setView] = createSignal<ImportSubview>(props.initialView ?? "menu");3133   const mode = () => props.mode ?? "existing";3234   const isOnboarding = () => mode() === "onboarding";35+  // When the caller deep-links into a subview, the back arrow exits the36+  // ImportView entirely. Otherwise it returns to the import menu.37+  const subviewBack = () => (props.initialView ? props.onBack() : setView("menu"));3338 3439   return (3540     <div class={isOnboarding() ? "peach-lock-view" : "peach-overlay-view ov-enter-right"} style="display:flex">@@ -45,7 +50,7 @@4550         <PeachScriptImport4651           mode={mode()}4752           replacesExistingVault={props.replacesExistingVault}48-          onBack={() => setView("menu")}53+          onBack={subviewBack}4954           onImport={props.onImport}5055         />5156       </Show>@@ -53,7 +58,7 @@5358         <FileImport5459           mode={mode()}5560           replacesExistingVault={props.replacesExistingVault}56-          onBack={() => setView("menu")}61+          onBack={subviewBack}5762           onImport={props.onImport}5863         />5964       </Show>

view file

src/popup/views/Lock.tsx+26 −2
@@ -20,8 +20,8 @@2020   onUnlock: () => void | Promise<void>;2121 }2222 23-// "restore" = picker, "snapshots" = vault history, "file" = detail flow24-type RestoreSurface = "restore" | "snapshots" | "file" | null;23+// "restore" = picker, "snapshots" = vault history, "peachscript" / "file" = detail flows24+type RestoreSurface = "restore" | "snapshots" | "peachscript" | "file" | null;2525 2626 export function LockView(props: LockProps) {2727   const [password, setPassword] = createSignal("");@@ -134,6 +134,7 @@134134       <Match when={restoreSurface() === "restore"}>135135         <RestorePickerView136136           onBack={() => setRestoreSurface(null)}137+          onPickPeachScript={() => setRestoreSurface("peachscript")}137138           onPickFile={() => setRestoreSurface("file")}138139           onPickSnapshots={() => setRestoreSurface("snapshots")}139140         />@@ -147,11 +148,26 @@147148         />148149       </Match>149150 151+      {/* ── PeachScript restore ───────────────────────────────────── */}152+      <Match when={restoreSurface() === "peachscript"}>153+        <ImportView154+          mode="onboarding"155+          replacesExistingVault={props.hasVault}156+          initialView="peachscript"157+          onBack={() => setRestoreSurface("restore")}158+          onImport={async () => {159+            setRestoreSurface(null);160+            await props.onUnlock();161+          }}162+        />163+      </Match>164+150165       {/* ── File restore ──────────────────────────────────────────── */}151166       <Match when={restoreSurface() === "file"}>152167         <ImportView153168           mode="onboarding"154169           replacesExistingVault={props.hasVault}170+          initialView="file"155171           onBack={() => setRestoreSurface("restore")}156172           onImport={async () => {157173             setRestoreSurface(null);@@ -354,6 +370,7 @@354370 355371 function RestorePickerView(props: {356372   onBack: () => void;373+  onPickPeachScript: () => void;357374   onPickFile: () => void;358375   onPickSnapshots: () => void;359376 }) {@@ -380,6 +397,13 @@380397 381398       <section class="peach-lock-panel peach-lock-panel--restore">382399         <p class="peach-hint" style="margin-bottom:2px;">How did you back up your data?</p>400+401+        <button class="peach-lock-option" onClick={props.onPickPeachScript}>402+          <span class="peach-lock-option-title">peachscript</span>403+          <span class="peach-lock-option-copy">404+            A string of Peach symbols you exported from another Peach device. You'll need the backup password you set at the time.405+          </span>406+        </button>383407 384408         <button class="peach-lock-option" onClick={props.onPickFile}>385409           <span class="peach-lock-option-title">backup file</span>

view file