73 lines
1.9 KiB
Svelte
73 lines
1.9 KiB
Svelte
|
|
<script lang="ts">
|
||
|
|
import '../app.css';
|
||
|
|
import { onMount } from 'svelte';
|
||
|
|
import { page } from '$app/stores';
|
||
|
|
import { goto } from '$app/navigation';
|
||
|
|
import { dev } from '$app/environment';
|
||
|
|
import { authState, checkAuth, consumeKeyParam } from '$lib/auth.svelte';
|
||
|
|
import { precacheAll } from '$lib/precache.svelte';
|
||
|
|
|
||
|
|
let { children } = $props();
|
||
|
|
let booted = $state(false);
|
||
|
|
|
||
|
|
onMount(async () => {
|
||
|
|
if ('serviceWorker' in navigator) {
|
||
|
|
if (dev) {
|
||
|
|
const regs = await navigator.serviceWorker.getRegistrations();
|
||
|
|
await Promise.all(regs.map((r) => r.unregister()));
|
||
|
|
const keys = await caches.keys();
|
||
|
|
await Promise.all(keys.map((k) => caches.delete(k)));
|
||
|
|
} else {
|
||
|
|
navigator.serviceWorker
|
||
|
|
.register('/service-worker.js', { type: 'module' })
|
||
|
|
.catch((err) => console.warn('sw register failed:', err));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const keyResult = await consumeKeyParam();
|
||
|
|
if (keyResult !== 'success') await checkAuth();
|
||
|
|
|
||
|
|
const path = $page.url.pathname;
|
||
|
|
if (authState() === 'signed-out' && path !== '/login') {
|
||
|
|
const params = new URLSearchParams({ next: path });
|
||
|
|
if (keyResult === 'failed') params.set('error', 'qr');
|
||
|
|
await goto('/login?' + params.toString(), { replaceState: true });
|
||
|
|
}
|
||
|
|
|
||
|
|
// Production-only: kick off audio/image bulk precache once authenticated.
|
||
|
|
// SW does the work; failures non-fatal.
|
||
|
|
if (!dev && authState() === 'signed-in') {
|
||
|
|
precacheAll().catch(() => undefined);
|
||
|
|
}
|
||
|
|
|
||
|
|
booted = true;
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
{#if booted}
|
||
|
|
{@render children()}
|
||
|
|
{:else}
|
||
|
|
<div class="splash">
|
||
|
|
<div class="ring" aria-hidden="true"></div>
|
||
|
|
</div>
|
||
|
|
{/if}
|
||
|
|
|
||
|
|
<style>
|
||
|
|
.splash {
|
||
|
|
flex: 1;
|
||
|
|
display: grid;
|
||
|
|
place-items: center;
|
||
|
|
}
|
||
|
|
.ring {
|
||
|
|
width: 32px;
|
||
|
|
height: 32px;
|
||
|
|
border-radius: 50%;
|
||
|
|
border: 2px solid var(--rule);
|
||
|
|
border-top-color: var(--accent);
|
||
|
|
animation: spin 0.8s linear infinite;
|
||
|
|
}
|
||
|
|
@keyframes spin {
|
||
|
|
to { transform: rotate(360deg); }
|
||
|
|
}
|
||
|
|
</style>
|