feat(phase3): PWA, auto-discovery, bookmarklet, multi-tab sync

- PWA: manifest, service worker (cache-first static, network-first API),
  offline page, install prompt banner
- Auto-discovery: Docker socket + Traefik API scanning, approval UI
- Quick-add bookmarklet: popup-based add page, favicon auto-detect
- Multi-tab sync: BroadcastChannel for theme + data changes
- i18n translations for all new strings (EN/RU)
This commit is contained in:
2026-03-25 00:59:19 +03:00
parent c6a7de895d
commit dd6958b4d6
28 changed files with 1712 additions and 266 deletions
+38
View File
@@ -0,0 +1,38 @@
<script lang="ts">
import { t } from 'svelte-i18n';
import { WifiOff, RefreshCw } from 'lucide-svelte';
function retry() {
window.location.reload();
}
</script>
<svelte:head>
<title>{$t('offline.title')}</title>
</svelte:head>
<div class="flex min-h-[60vh] flex-col items-center justify-center gap-6 px-4 text-center">
<div
class="flex h-20 w-20 items-center justify-center rounded-full bg-muted"
>
<WifiOff class="h-10 w-10 text-muted-foreground" />
</div>
<div class="space-y-2">
<h1 class="text-2xl font-bold text-foreground">
{$t('offline.title')}
</h1>
<p class="max-w-md text-muted-foreground">
{$t('offline.description')}
</p>
</div>
<button
type="button"
onclick={retry}
class="inline-flex items-center gap-2 rounded-lg bg-primary px-6 py-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90"
>
<RefreshCw class="h-4 w-4" />
{$t('offline.retry')}
</button>
</div>