Offline access: read recent mail without a connection

An opt-in per device (Settings → Security → Offline access) installs a
service worker that keeps the newest 50 Inbox conversations, and the ones
opened recently, for reading when the server cannot be reached. While
online everything still comes from the server; the saved copy is only the
fallback, marked X-WM-Offline so the app knows it is offline.

Offline, an amber cloud next to the theme toggle says so and when mail was
last saved; actions that need the server are greyed out and say "Not
available offline"; conversations and folders not saved here are faded or
say so. A probe notices the server coming back, shows "Back online" and
refreshes everything. Saved mail is wiped on sign-out, on any 401, and when
another user signs in. nginx never caches /sw.js, so releases reach it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 18:54:17 +02:00
co-authored by Claude Opus 5.5
parent 139fff826e
commit a2c52f33a8
15 changed files with 1245 additions and 30 deletions
+21
View File
@@ -545,6 +545,27 @@ export const en = {
"theme.dark": "Dark",
"theme.system": "System",
"theme.toggle": "Toggle theme",
"offline.label": "Offline",
"offline.backOnline": "Back online",
"offline.explainSaved": "Offline — showing mail saved on this device, last updated {when}.",
"offline.explainSavedNoTime": "Offline — showing mail saved on this device.",
"offline.explainNotSaved":
"Can't reach the server. To read recent mail without a connection, turn on offline access in Settings → Security.",
"offline.noticeSaved": "You're offline. Recent mail is still available.",
"offline.noticeNotSaved": "You're offline — can't reach the server.",
"offline.notAvailable": "Not available offline",
"offline.threadNotSaved": "This conversation isn't saved on this device.",
"offline.folderNotSaved": "This folder isn't saved on this device.",
"offline.searchPlaceholder": "Search (offline)",
"offline.cantReach": "Can't reach the server.",
"offline.settingTitle": "Offline access",
"offline.settingHelp":
"Keep your newest 50 Inbox conversations, and the ones you open, on this device, so you can read them without a connection. They are stored unencrypted in this browser and removed when you sign out — leave this off on shared computers.",
"offline.settingStatus": "{count} conversations saved · {size} · updated {when}",
"offline.settingStatusNoTime": "{count} conversations saved · {size}",
"offline.settingSaving": "Saving recent mail…",
"offline.settingUnsupported":
"Not available here: browsers allow offline access only when the app is opened over HTTPS.",
} as const;
export type MessageKey = keyof typeof en;