import { mount } from 'svelte' import './app.css' import App from './App.svelte' import DemoBoard from './lib/components/DemoBoard.svelte' import { demoActor } from './lib/demo' // `/demo/` is its own page, not a mode of the app: it renders another // account's *public* records read-only, so it must not load IndexedDB, start an // OAuth session, or let the app rewrite the address bar (see url.ts). Branching // at the mount is what keeps all of that out of the picture. const target = document.getElementById('app')! const actor = demoActor() const app = actor ? mount(DemoBoard, { target, props: { actor } }) : mount(App, { target }) // Register the service worker (built by serviceWorkerPlugin in vite.config) so // the app cold-loads offline. Prod-only — there's no sw.js during `vite dev`. // `updateViaCache: "none"` keeps the SW script itself always revalidated so a // new deploy is picked up promptly. // // A long-lived tab must not be allowed to keep running an old bundle: every // instance at this origin shares one OAuth session store, so an outdated // instance can sign the user out from under a healthy one. That first showed up // as @atproto/oauth-client deleting the shared session after a stale call came // back 401 invalid_token; the same hazard applies to the current PDS-issued // session, where a stale tab holds a stale access token and can rotate the // refresh token out from under this one. So: check for a new worker // whenever the tab comes back to the foreground, and reload as soon as one takes // control (the new SW calls skipWaiting, so control changes on its first // activation). if (import.meta.env.PROD && 'serviceWorker' in navigator) { // A controller change on a page that had none is just the first-ever SW // claiming this load — nothing to reload for. const hadController = navigator.serviceWorker.controller != null let reloading = false navigator.serviceWorker.addEventListener('controllerchange', () => { if (!hadController || reloading) return reloading = true window.location.reload() }) window.addEventListener('load', () => { navigator.serviceWorker .register('/sw.js', { updateViaCache: 'none' }) .then((reg) => { const check = () => { if (!document.hidden) void reg.update().catch(() => {}) } document.addEventListener('visibilitychange', check) // Backstop for an instance that stays visible for days (a pinned tab or // a dock/home-screen window that is never re-focused). setInterval(check, 60 * 60 * 1000) }) .catch(() => {}) }) } export default app