Server (kez-chat/src/) - push.rs: VAPID (PEM/PKCS#8) auto-generated on first run; StoredSubscription store table; PushSender using IsahcWebPushClient; fanout drops 410/404 subs automatically. Push payload carries metadata only ({type,to,seq}) — never plaintext or ciphertext. - api.rs: GET /v1/push/vapid-public-key, POST /v1/push/subscribe/:handle, POST /v1/push/unsubscribe/:handle. Auth via X-KEZ-Auth: <ts>:<sig>, canonical message binds the endpoint URL so headers can't be replayed against other subs. - messages.rs: after broker.publish, fire-and-forget push.fanout for offline recipients. - config.rs: --vapid-key-path, --vapid-subject (env-backed). - main.rs: load_or_generate_vapid on startup. Web client (kez-chat/web/src/) - vite.config.ts: switched vite-plugin-pwa to injectManifest mode. - sw.ts: custom service worker with workbox precache, NetworkOnly for /v1/*, NavigationRoute SPA fallback, push + notificationclick handlers (focus existing tab via postMessage, or open a new one). - lib/push.ts: enablePush / disablePush / isPushSubscribed + iOS PWA-install detection. - routes/Settings.svelte: "Background notifications (Web Push)" section with toggle and iOS Add-to-Home-Screen nudge. - main.ts: bridge from SW navigate message to svelte-spa-router via location.hash. Chat UX (routes/Messages.svelte) - Bubbles now shrink-wrap to content with WhatsApp-style asymmetric corners and inline bottom-right timestamps. Old layout used nested block-level divs inside max-w-[78%], which stretched every bubble to full width regardless of content. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
41 lines
1.1 KiB
JSON
41 lines
1.1 KiB
JSON
{
|
|
"name": "kez-chat-web",
|
|
"version": "0.1.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "tsc -b && vite build",
|
|
"preview": "vite preview",
|
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
},
|
|
"dependencies": {
|
|
"@bokuweb/zstd-wasm": "^0.0.22",
|
|
"@noble/curves": "^1.6.0",
|
|
"@noble/hashes": "^1.5.0",
|
|
"@scure/base": "^1.1.9",
|
|
"@scure/bip39": "^2.2.0",
|
|
"canonicalize": "^2.0.0",
|
|
"emoji-picker-element": "^1.29.1",
|
|
"idb-keyval": "^6.2.1",
|
|
"nostr-tools": "^2.23.5",
|
|
"svelte-spa-router": "^4.0.1"
|
|
},
|
|
"devDependencies": {
|
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
|
"@tailwindcss/vite": "^4.0.0",
|
|
"@tsconfig/svelte": "^5.0.0",
|
|
"@types/node": "^22.0.0",
|
|
"@vite-pwa/assets-generator": "^1.0.2",
|
|
"svelte": "^5.0.0",
|
|
"svelte-check": "^4.0.0",
|
|
"tailwindcss": "^4.0.0",
|
|
"typescript": "^5.6.0",
|
|
"vite": "^5.4.0",
|
|
"vite-plugin-pwa": "^1.3.0",
|
|
"workbox-precaching": "^7.4.1",
|
|
"workbox-routing": "^7.4.1",
|
|
"workbox-strategies": "^7.4.1"
|
|
}
|
|
}
|