70 lines
2.6 KiB
TypeScript
70 lines
2.6 KiB
TypeScript
/*
|
|
* What the service worker cannot work out for itself.
|
|
*
|
|
* The worker can act on mail — see the note on `jmap()` in sw.js — but it
|
|
* cannot read a catalog or a store. It is plain JavaScript copied into the
|
|
* build, outside the bundle, with no i18n and no idea which mailbox is the
|
|
* archive. Both of those are things a tab knows and can simply write down.
|
|
*
|
|
* So the app leaves a short briefing in the same cache it uses for every other
|
|
* handoff, and the worker reads it when a notification arrives. Where there is
|
|
* none, the worker offers no actions at all rather than guessing: an untitled
|
|
* button that files mail somewhere is worse than a notification you have to
|
|
* open.
|
|
*
|
|
* That means the actions appear once ihasmail has been opened since the worker
|
|
* was installed, which is the same condition background notifications already
|
|
* carry — a push subscription has to be renewed from a tab too.
|
|
*/
|
|
import { withBase } from "./basePath";
|
|
import { SW_CACHE_NAME } from "./swCache";
|
|
import { t } from "./i18n";
|
|
|
|
export const FACTS_KEY = "/ihasmail-worker-facts";
|
|
|
|
export interface WorkerFacts {
|
|
/** The account the notifications are about. */
|
|
accountId: string;
|
|
/** Where Archive files to; null where the account has no archive folder. */
|
|
archiveId: string | null;
|
|
/** The worker's own user-visible text, in the language this tab is in. */
|
|
strings: {
|
|
newMail: string;
|
|
newMessage: string;
|
|
noSubject: string;
|
|
archive: string;
|
|
markRead: string;
|
|
failed: string;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Write the briefing.
|
|
*
|
|
* Called again whenever what is in it could have changed — the language, the
|
|
* account, the archive folder — because it is what the worker will still be
|
|
* reading in a week's time. Rewriting it is one cache put; there is nothing to
|
|
* gain by working out whether it differs.
|
|
*/
|
|
export async function publishWorkerFacts(accountId: string | null, archiveId: string | null): Promise<void> {
|
|
if (typeof caches === "undefined" || !accountId) return;
|
|
const facts: WorkerFacts = {
|
|
accountId,
|
|
archiveId,
|
|
strings: {
|
|
newMail: t("New mail"),
|
|
newMessage: t("New message"),
|
|
noSubject: t("(no subject)"),
|
|
archive: t("Archive"),
|
|
markRead: t("Mark as read"),
|
|
failed: t("Could not do that — open ihasmail and try again"),
|
|
},
|
|
};
|
|
try {
|
|
const cache = await caches.open(SW_CACHE_NAME);
|
|
await cache.put(withBase(FACTS_KEY), new Response(JSON.stringify(facts), { headers: { "content-type": "application/json" } }));
|
|
} catch {
|
|
/* no cache storage: the worker falls back to a notification with no actions */
|
|
}
|
|
}
|