release-notes.ts

2.5 KB · raw

1/**2 * Build-time release notes for the "what's new" screen.3 *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.7 *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.11 */1213declare const __PEACH_VERSION__: string;1415export interface ReleaseNote {16  heading: string;17  body: string;18  breaking?: boolean;19}2021export const PEACH_VERSION: string = typeof __PEACH_VERSION__ !== "undefined"22  ? __PEACH_VERSION__23  : "0.0.0";2425export const CURRENT_NOTICE_ID = "vault-v4-android-minimum-2026-09-05";2627export const CURRENT_NOTES: ReleaseNote[] = [28  {29    heading: "Passphrases & long passwords",30    body: "Peach now supports passphrases and passwords up to 256 characters. Existing vaults remain fully readable.",31  },32  {33    heading: "Update your Android app first",34    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.",35    breaking: true,36  },37];3839export function hasReleaseNotes(): boolean {40  return CURRENT_NOTES.length > 0;41}4243const WHATS_NEW_SEEN_KEY = "peach_whats_new_seen";4445export async function shouldShowWhatsNew(): Promise<boolean> {46  if (!hasReleaseNotes()) return false;47  try {48    const seen = await chrome.storage.local.get(WHATS_NEW_SEEN_KEY);49    const last = seen[WHATS_NEW_SEEN_KEY];50    // A fresh install has no stored version — there is nothing to catch up51    // on, so the screen never appears. It only fires on an upgrade from a52    // previously-seen version. Mirrors Android's WhatsNewScreen gate.53    if (last === undefined) return false;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;61  } catch {62    return false;63  }64}6566export async function markWhatsNewSeen(): Promise<void> {67  try {68    await chrome.storage.local.set({ [WHATS_NEW_SEEN_KEY]: CURRENT_NOTICE_ID });69  } catch {70    // best-effort — the screen just won't reshow, which is the lesser evil71  }72}