diff options
| author | Adam Soltys <[email protected]> | 2024-10-19 21:55:05 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-10-19 21:55:05 -0700 |
| commit | de6c1ad727379c5ebe8550124ea9313979124953 (patch) | |
| tree | 67df287630d6e76484be526522038022a1ccf546 /src | |
| parent | 002cd9134d2e23bec34f838f6d6fefba41f2d530 (diff) | |
| download | coinos-ui-de6c1ad727379c5ebe8550124ea9313979124953.tar.gz coinos-ui-de6c1ad727379c5ebe8550124ea9313979124953.zip | |
push notifications
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.html | 6 | ||||
| -rw-r--r-- | src/locales/en.json | 3 | ||||
| -rw-r--r-- | src/routes/(app)/locations/+server.ts | 17 | ||||
| -rw-r--r-- | src/routes/(app)/settings/[...tab]/+page.server.ts | 1 | ||||
| -rw-r--r-- | src/routes/(app)/settings/[...tab]/_pos.svelte | 75 | ||||
| -rw-r--r-- | src/routes/(app)/subscription/+server.ts | 7 | ||||
| -rw-r--r-- | src/routes/(app)/subscription/delete/+server.ts | 8 | ||||
| -rw-r--r-- | src/routes/map/+page.server.ts | 12 | ||||
| -rw-r--r-- | src/routes/start/+server.ts | 10 | ||||
| -rw-r--r-- | src/service-worker.js | 32 |
10 files changed, 116 insertions, 55 deletions
diff --git a/src/app.html b/src/app.html index df6e9567..5903f2ff 100644 --- a/src/app.html +++ b/src/app.html @@ -13,6 +13,12 @@ /> <meta name="keywords" content="open source bitcoin lightning web wallet" /> <meta name="theme-color" content="#fff" /> + <meta name="apple-mobile-web-app-capable" content="yes" /> + <meta + name="apple-mobile-web-app-status-bar-style" + content="black-translucent" + /> + <link rel="apple-touch-icon" href="/images/icon-160.png" /> <link rel="manifest" href="/manifest.webmanifest" /> %sveltekit.head% </head> diff --git a/src/locales/en.json b/src/locales/en.json index 369533ad..2171febe 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -257,7 +257,8 @@ "autoWithdrawDescription": "Enable withdrawals to an external address when your balance reaches a given threshold", "notifications": "Email notifications", "pushNotifications": "Push notifications", - "pushNotificationsDesc": "Get push notifications to your phone's status bar", + "pushNotificationsDesc": "Get payment notifications on your device", + "pushNotificationsDisabled": "You've denied notification permission on this device. Check your browser settings if you want to undo that.", "notificationsDesc": "Receive an email whenever a payment lands in your account", "seedPhrase": "Seed phrase", "nostrKeys": "Nostr key", diff --git a/src/routes/(app)/locations/+server.ts b/src/routes/(app)/locations/+server.ts index 987459bc..f3fa1023 100644 --- a/src/routes/(app)/locations/+server.ts +++ b/src/routes/(app)/locations/+server.ts @@ -2,14 +2,15 @@ import { get } from "$lib/utils"; import { json } from "@sveltejs/kit"; export async function GET({ setHeaders }) { - let locations = []; + let locations = []; - try { - ({ locations } = await get("/locations")); - setHeaders({ "cache-control": "public, max-age=600" }); - } catch (e) { - console.log("failed to fetch locations"); - } + try { + ({ locations } = await get("/locations")); + console.log(locations); + setHeaders({ "cache-control": "public, max-age=600" }); + } catch (e) { + console.log("failed to fetch locations"); + } - return json({ locations }); + return json({ locations }); } diff --git a/src/routes/(app)/settings/[...tab]/+page.server.ts b/src/routes/(app)/settings/[...tab]/+page.server.ts index 42639b38..7c1542c0 100644 --- a/src/routes/(app)/settings/[...tab]/+page.server.ts +++ b/src/routes/(app)/settings/[...tab]/+page.server.ts @@ -14,6 +14,7 @@ export const actions = { if (form.tab === "pos") { form.notify = form.notify === "on"; + form.push = form.push === "on"; form.nip5 = form.nip5 === "on"; form.prompt = form.prompt === "on"; form.autowithdraw = form.autowithdraw === "on"; diff --git a/src/routes/(app)/settings/[...tab]/_pos.svelte b/src/routes/(app)/settings/[...tab]/_pos.svelte index 7ccaa69f..7ea76c53 100644 --- a/src/routes/(app)/settings/[...tab]/_pos.svelte +++ b/src/routes/(app)/settings/[...tab]/_pos.svelte @@ -1,12 +1,14 @@ <script> - import { tick } from "svelte"; + import { onMount, tick } from "svelte"; + import { browser } from "$app/environment"; import Icon from "$comp/Icon.svelte"; import Numpad from "$comp/Numpad.svelte"; import LocaleSelector from "$comp/LocaleSelector.svelte"; import Toggle from "$comp/Toggle.svelte"; import { locale, t } from "$lib/translations"; - import { success, fail } from "$lib/utils"; + import { post, success, fail } from "$lib/utils"; import { page } from "$app/stores"; + import { PUBLIC_VAPID_PUBKEY } from "$env/static/public"; export let user, rates, submit; @@ -39,35 +41,48 @@ if (!user.reserve) user.reserve = 100000; let reserveEl, thresholdEl; - let subscription; - $: updateNotifications(user.push); + let push, pm; + + onMount(async () => { + if (!browser) return; + + pm = + navigator?.serviceWorker && + (await navigator.serviceWorker.getRegistration()).pushManager; + + permission = await pm.permissionState({ + userVisibleOnly: true, + applicationServerKey: PUBLIC_VAPID_PUBKEY, + }); + + push = permission === "granted"; + }); + + let permission; + $: updateNotifications(push); let updateNotifications = async (push) => { - if (push && navigator.serviceWorker) { - const VAPID_PUBLIC_KEY = - "BEfgMDTeAn1F8ZQUGC6v5iKTD86zYXaa3QVr1E-ylKXC5c24JplcfSAN9PDlXAsVtUd3cU6j4-LsX_TKQzz_yDQ"; + let subscription; + if (!browser || !pm) return (push = false); - const swRegistration = await navigator.serviceWorker.getRegistration(); - const pushManager = swRegistration.pushManager; - if (!isPushManagerActive(pushManager)) { - console.log("not active"); - return; - } - subscription = await pushManager.subscribe({ - userVisibleOnly: true, - applicationServerKey: VAPID_PUBLIC_KEY, - }); + if (permission === "granted") { + subscription = await pm.getSubscription(); } - }; - function isPushManagerActive(pushManager) { - if (pushManager) return true; + if (subscription && !push) { + return post("/subscription/delete", { subscription }); + } - if (!window.navigator.standalone) { - console.log("not standalone"); + if (push && permission === "prompt") { + subscription = await pm.subscribe({ + userVisibleOnly: true, + applicationServerKey: PUBLIC_VAPID_PUBKEY, + }); } - return false; - } + if (subscription) { + await post("/subscription", { subscription }); + } + }; </script> <div> @@ -105,15 +120,19 @@ <div> <div class="flex justify-between items-center"> <span class="font-bold">{$t("user.settings.pushNotifications")}</span> - <Toggle id="push" bind:value={user.push} /> + {#if permission !== "denied"} + <Toggle id="push" bind:value={push} /> + {/if} </div> <p class="text-secondary mt-1 w-9/12"> - {$t("user.settings.pushNotificationsDesc")} + {#if permission === "denied"} + {$t("user.settings.pushNotificationsDisabled")} + {:else} + {$t("user.settings.pushNotificationsDesc")} + {/if} </p> </div> -{JSON.stringify(subscription)} - <div> <div class="flex justify-between items-center"> <span class="font-bold">{$t("user.settings.tipPrompt")}</span> diff --git a/src/routes/(app)/subscription/+server.ts b/src/routes/(app)/subscription/+server.ts index 8ae3f965..47dfc770 100644 --- a/src/routes/(app)/subscription/+server.ts +++ b/src/routes/(app)/subscription/+server.ts @@ -2,10 +2,7 @@ import { auth, post } from "$lib/utils"; import { json } from "@sveltejs/kit"; export async function POST({ cookies, request }) { - const result = await post( - "/subscription", - await request.json(), - auth(cookies), - ); + const body = await request.json(); + const result = await post("/subscription", body, auth(cookies)); return json(result); } diff --git a/src/routes/(app)/subscription/delete/+server.ts b/src/routes/(app)/subscription/delete/+server.ts new file mode 100644 index 00000000..f4c8357c --- /dev/null +++ b/src/routes/(app)/subscription/delete/+server.ts @@ -0,0 +1,8 @@ +import { auth, post } from "$lib/utils"; +import { json } from "@sveltejs/kit"; + +export async function POST({ cookies, request }) { + const body = await request.json(); + const result = await post("/subscription/delete", body, auth(cookies)); + return json(result); +} diff --git a/src/routes/map/+page.server.ts b/src/routes/map/+page.server.ts index 5012e7e3..b921cc22 100644 --- a/src/routes/map/+page.server.ts +++ b/src/routes/map/+page.server.ts @@ -1,11 +1,11 @@ import { get } from "$lib/utils"; -export let load = async () => { - let data = { locations: [] }; +export const load = async () => { + let data = { locations: [] }; - try { - data = await get("/locations"); - } catch (e) {} + try { + data = await get("/locations"); + } catch (e) {} - return data; + return data; }; diff --git a/src/routes/start/+server.ts b/src/routes/start/+server.ts index 2a1d88c3..58bca85f 100644 --- a/src/routes/start/+server.ts +++ b/src/routes/start/+server.ts @@ -1,10 +1,10 @@ import { redirect } from "@sveltejs/kit"; export async function GET({ cookies }) { - let username = cookies.get("username"); - if (username) { - redirect(307, `/invoice`); - } + const username = cookies.get("username"); + if (username) { + redirect(307, `/${username}/receive`); + } - redirect(307, "/"); + redirect(307, "/"); } diff --git a/src/service-worker.js b/src/service-worker.js index fee7eee0..fa934333 100644 --- a/src/service-worker.js +++ b/src/service-worker.js @@ -4,6 +4,34 @@ self.addEventListener("install", (event) => {}); self.addEventListener("activate", (event) => {}); self.addEventListener("fetch", (event) => {}); self.addEventListener("push", (event) => { - const pushData = event.data.json(); - self.registration.showNotification(pushData.title, pushData); + const { title, body, url } = event.data.json(); + const icon = "/images/icon.png"; + const badge = "/images/badge.png"; + self.registration.showNotification(title, { + body, + icon, + badge, + data: { url }, + }); +}); + +self.addEventListener("notificationclick", (event) => { + event.notification.close(); + + const url = event.notification.data.url || "/"; + + event.waitUntil( + clients + .matchAll({ type: "window", includeUncontrolled: true }) + .then((clientList) => { + for (const client of clientList) { + if (client.url === url && "focus" in client) { + return client.focus(); + } + } + if (clients.openWindow) { + return clients.openWindow(url); + } + }), + ); }); |
