e4155d95f68e

fix: Show changelog only for intentional notices (v5.2.5)

time
2026-09-06 19:35 UTC · 1 month ago
machine
koh2
parent
46fd698ce73c
5 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/shared/release-notes.test.ts+15 −9src/shared/release-notes.ts+16 −10
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "5.2.4",4+  "version": "5.2.5",55   "description": "Zero-knowledge password manager",66   "browser_specific_settings": {77     "gecko": {

view file

manifest.json+1 −1
@@ -2,7 +2,7 @@22   "manifest_version": 3,33   "minimum_chrome_version": "116",44   "name": "Peach Password Manager",5-  "version": "5.2.4",5+  "version": "5.2.5",66   "description": "Zero-knowledge password manager",77   "action": {88     "default_popup": "src/popup/index.html",

view file

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

view file

src/shared/release-notes.test.ts+15 −9
@@ -17,6 +17,7 @@1717 // Import after globals are stubbed so the module captures the mock.1818 const {1919   PEACH_VERSION,20+  CURRENT_NOTICE_ID,2021   CURRENT_NOTES,2122   hasReleaseNotes,2223   shouldShowWhatsNew,@@ -45,34 +46,39 @@4546     expect(hasReleaseNotes()).toBe(true);4647   });4748 48-  it("shouldShowWhatsNew returns true when stored version differs", async () => {49-    store["peach_whats_new_seen"] = "0.0.1";49+  it("shouldShowWhatsNew returns true when the important notice changes", async () => {50+    store["peach_whats_new_seen"] = "previous-critical-notice";5051     expect(await shouldShowWhatsNew()).toBe(true);5152   });5253 53-  it("shouldShowWhatsNew returns false when stored version matches", async () => {54-    store["peach_whats_new_seen"] = PEACH_VERSION;54+  it("shouldShowWhatsNew returns false when the important notice matches", async () => {55+    store["peach_whats_new_seen"] = CURRENT_NOTICE_ID;5556     expect(await shouldShowWhatsNew()).toBe(false);5657   });5758 59+  it("does not reshow unchanged notes after a patch-version dismissal", async () => {60+    store["peach_whats_new_seen"] = "5.2.3";61+    expect(await shouldShowWhatsNew()).toBe(false);62+    expect(store["peach_whats_new_seen"]).toBe(CURRENT_NOTICE_ID);63+  });64+5865   it("shouldShowWhatsNew returns false on a fresh install (nothing seen yet)", async () => {5966     expect(await shouldShowWhatsNew()).toBe(false);6067   });6168 6269   it("markWhatsNewSeen stores the current version and suppresses reshowing", async () => {6370     // Simulate an upgrade from a previously-seen older version.64-    store["peach_whats_new_seen"] = "0.0.1";71+    store["peach_whats_new_seen"] = "previous-critical-notice";6572     expect(await shouldShowWhatsNew()).toBe(true);6673     await markWhatsNewSeen();6774     expect(await shouldShowWhatsNew()).toBe(false);68-    expect(store["peach_whats_new_seen"]).toBe(PEACH_VERSION);75+    expect(store["peach_whats_new_seen"]).toBe(CURRENT_NOTICE_ID);6976   });7077 71-  it("a version bump re-triggers the screen", async () => {78+  it("a new important notice re-triggers the screen", async () => {7279     await markWhatsNewSeen();7380     expect(await shouldShowWhatsNew()).toBe(false);74-    // Simulate an older stored version (as if the user upgraded)75-    store["peach_whats_new_seen"] = "5.0.0";81+    store["peach_whats_new_seen"] = "future-breaking-notice";7682     expect(await shouldShowWhatsNew()).toBe(true);7783   });7884 });

view file

src/shared/release-notes.ts+16 −10
@@ -1,15 +1,13 @@11 /**22  * Build-time release notes for the "what's new" screen.33  *4- * The screen appears once after unlock when the build version differs from the5- * last version the user acknowledged. `__PEACH_VERSION__` is injected by Vite6- * from package.json at build time. When `CURRENT_NOTES` is empty the screen is7- * skipped entirely — no content, no interruption.4+ * The screen appears once after unlock when CURRENT_NOTICE_ID differs from the5+ * last notice the user acknowledged. The app version is display-only: routine6+ * patch releases must not replay unchanged notes.87  *9- * To ship a new changelog: bump the version in package.json (which Vite injects10- * as `__PEACH_VERSION__`), then add entries to `CURRENT_NOTES` below. The11- * version mismatch triggers the screen on next unlock; "Continue" stores the12- * version and suppresses it until the next bump.8+ * To ship an important/breaking changelog: update CURRENT_NOTES and deliberately9+ * change CURRENT_NOTICE_ID. "Continue" stores that ID and suppresses the screen10+ * until the next intentional notice revision.1311  */1412 1513 declare const __PEACH_VERSION__: string;@@ -24,6 +22,8 @@2422   ? __PEACH_VERSION__2523   : "0.0.0";2624 25+export const CURRENT_NOTICE_ID = "vault-v4-android-minimum-2026-09-05";26+2727 export const CURRENT_NOTES: ReleaseNote[] = [2828   {2929     heading: "Passphrases & long passwords",@@ -51,7 +51,13 @@5151     // on, so the screen never appears. It only fires on an upgrade from a5252     // previously-seen version. Mirrors Android's WhatsNewScreen gate.5353     if (last === undefined) return false;54-    return last !== PEACH_VERSION;54+    if (typeof last === "string" && /^\d+\.\d+\.\d+$/.test(last)) {55+      // Versions through v5.2.4 stored the app version. Any such value proves56+      // this same static V4 notice was already acknowledged; migrate silently.57+      await chrome.storage.local.set({ [WHATS_NEW_SEEN_KEY]: CURRENT_NOTICE_ID });58+      return false;59+    }60+    return last !== CURRENT_NOTICE_ID;5561   } catch {5662     return false;5763   }@@ -59,7 +65,7 @@5965 6066 export async function markWhatsNewSeen(): Promise<void> {6167   try {62-    await chrome.storage.local.set({ [WHATS_NEW_SEEN_KEY]: PEACH_VERSION });68+    await chrome.storage.local.set({ [WHATS_NEW_SEEN_KEY]: CURRENT_NOTICE_ID });6369   } catch {6470     // best-effort — the screen just won't reshow, which is the lesser evil6571   }

view file