aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-10-19 21:55:05 -0700
committerAdam Soltys <[email protected]>2024-10-19 21:55:05 -0700
commitde6c1ad727379c5ebe8550124ea9313979124953 (patch)
tree67df287630d6e76484be526522038022a1ccf546 /src
parent002cd9134d2e23bec34f838f6d6fefba41f2d530 (diff)
downloadcoinos-ui-de6c1ad727379c5ebe8550124ea9313979124953.tar.gz
coinos-ui-de6c1ad727379c5ebe8550124ea9313979124953.zip
push notifications
Diffstat (limited to 'src')
-rw-r--r--src/app.html6
-rw-r--r--src/locales/en.json3
-rw-r--r--src/routes/(app)/locations/+server.ts17
-rw-r--r--src/routes/(app)/settings/[...tab]/+page.server.ts1
-rw-r--r--src/routes/(app)/settings/[...tab]/_pos.svelte75
-rw-r--r--src/routes/(app)/subscription/+server.ts7
-rw-r--r--src/routes/(app)/subscription/delete/+server.ts8
-rw-r--r--src/routes/map/+page.server.ts12
-rw-r--r--src/routes/start/+server.ts10
-rw-r--r--src/service-worker.js32
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);
+ }
+ }),
+ );
});