service worker: use injectManifest

- a RPC framework is added for further use
- fix an error that the service worker is not
    registered until the settings opened
- added theme-color
- settings: added a item to indicate the offline
    availablity
This commit is contained in:
thislight 2024-10-15 20:30:08 +08:00
parent 3ea7072437
commit 559a352bc1
11 changed files with 341 additions and 19 deletions

View file

@ -5,6 +5,7 @@ import {
createEffect,
createMemo,
createRenderEffect,
createSignal,
ErrorBoundary,
lazy,
onCleanup,
@ -17,6 +18,14 @@ import {
import { $accounts, updateAcctInf } from "./accounts/stores.js";
import { useStore } from "@nanostores/solid";
import { DateFnScope, useLanguage } from "./platform/i18n.jsx";
import { useRegisterSW } from "virtual:pwa-register/solid";
import {
isJSONRPCResult,
ResultDispatcher,
type JSONRPC,
} from "./serviceworker/services.js";
import { makeEventListener } from "@solid-primitives/event-listener";
import { ServiceWorkerProvider } from "./platform/host.js";
const AccountSignIn = lazy(() => import("./accounts/SignIn.js"));
const AccountMastodonOAuth2Callback = lazy(
@ -58,6 +67,43 @@ const App: Component = () => {
const theme = useRootTheme();
const accts = useStore($accounts);
const lang = useLanguage();
const [serviceWorker, setServiceWorker] = createSignal<ServiceWorker>();
const dispatcher = new ResultDispatcher();
let checkAge = 0;
const untilServiceWorkerAlive = async (
worker: ServiceWorker,
expectedAge: number,
) => {
const [call, ret] = dispatcher.createTypedCall("ping", undefined);
worker.postMessage(await call);
const result = await ret;
console.assert(!result.error, result);
if (expectedAge === checkAge) {
setServiceWorker(worker);
}
};
makeEventListener(window, "message", (event: MessageEvent<JSONRPC>) => {
if (isJSONRPCResult(event.data)) {
dispatcher.dispatch(event.data.id, event.data);
}
});
const {
needRefresh: [needRefresh],
offlineReady: [offlineReady],
} = useRegisterSW({
onRegisteredSW(scriptUrl, reg) {
console.info("service worker is registered from %s", scriptUrl);
const active = reg?.active;
if (!active) {
console.warn("No service is in activating or activated");
return;
}
untilServiceWorkerAlive(active, checkAge++);
},
});
const clients = createMemo(() => {
return accts().map((x) => ({
@ -103,7 +149,15 @@ const App: Component = () => {
<ThemeProvider theme={theme()}>
<DateFnScope>
<ClientProvider value={clients}>
<Routing />
<ServiceWorkerProvider
value={{
needRefresh,
offlineReady,
serviceWorker,
}}
>
<Routing />
</ServiceWorkerProvider>
</ClientProvider>
</DateFnScope>
</ThemeProvider>