/** * Build-time release notes for the "what's new" screen. * * The screen appears once after unlock when CURRENT_NOTICE_ID differs from the * last notice the user acknowledged. The app version is display-only: routine * patch releases must not replay unchanged notes. * * To ship an important/breaking changelog: update CURRENT_NOTES and deliberately * change CURRENT_NOTICE_ID. "Continue" stores that ID and suppresses the screen * until the next intentional notice revision. */ declare const __PEACH_VERSION__: string; export interface ReleaseNote { heading: string; body: string; breaking?: boolean; } export const PEACH_VERSION: string = typeof __PEACH_VERSION__ !== "undefined" ? __PEACH_VERSION__ : "0.0.0"; export const CURRENT_NOTICE_ID = "vault-v4-android-minimum-2026-09-05"; export const CURRENT_NOTES: ReleaseNote[] = [ { heading: "Passphrases & long passwords", body: "Peach now supports passphrases and passwords up to 256 characters. Existing vaults remain fully readable.", }, { heading: "Update your Android app first", body: "Vault V4 is not readable by Peach Android before v2.15.3. Open Peach on Android → Settings → Update, or visit peachpasswords.com to download the latest version. Export a backup on Android before updating.", breaking: true, }, ]; export function hasReleaseNotes(): boolean { return CURRENT_NOTES.length > 0; } const WHATS_NEW_SEEN_KEY = "peach_whats_new_seen"; export async function shouldShowWhatsNew(): Promise { if (!hasReleaseNotes()) return false; try { const seen = await chrome.storage.local.get(WHATS_NEW_SEEN_KEY); const last = seen[WHATS_NEW_SEEN_KEY]; // A fresh install has no stored version — there is nothing to catch up // on, so the screen never appears. It only fires on an upgrade from a // previously-seen version. Mirrors Android's WhatsNewScreen gate. if (last === undefined) return false; if (typeof last === "string" && /^\d+\.\d+\.\d+$/.test(last)) { // Versions through v5.2.4 stored the app version. Any such value proves // this same static V4 notice was already acknowledged; migrate silently. await chrome.storage.local.set({ [WHATS_NEW_SEEN_KEY]: CURRENT_NOTICE_ID }); return false; } return last !== CURRENT_NOTICE_ID; } catch { return false; } } export async function markWhatsNewSeen(): Promise { try { await chrome.storage.local.set({ [WHATS_NEW_SEEN_KEY]: CURRENT_NOTICE_ID }); } catch { // best-effort — the screen just won't reshow, which is the lesser evil } }