aboutsummaryrefslogtreecommitdiffstats
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
parent002cd9134d2e23bec34f838f6d6fefba41f2d530 (diff)
downloadcoinos-ui-de6c1ad727379c5ebe8550124ea9313979124953.tar.gz
coinos-ui-de6c1ad727379c5ebe8550124ea9313979124953.zip
push notifications
-rw-r--r--.env.production3
-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
-rw-r--r--static/images/badge.pngbin0 -> 2642 bytes
-rw-r--r--static/images/icon-160.pngbin0 -> 6660 bytes
-rw-r--r--static/images/icon.pngbin0 -> 55975 bytes
-rw-r--r--static/images/icon.svg (renamed from static/images/symbol.svg)0
-rw-r--r--static/images/john.webpbin16970 -> 0 bytes
-rw-r--r--static/images/karnage.webpbin16158 -> 0 bytes
-rw-r--r--static/images/loft.jpgbin286853 -> 0 bytes
-rw-r--r--static/images/moneypot.jpgbin34030 -> 0 bytes
-rw-r--r--static/images/moneypot.pngbin278763 -> 0 bytes
-rw-r--r--static/images/secondl1ght.webpbin21366 -> 0 bytes
-rw-r--r--static/images/shauna.webpbin22036 -> 0 bytes
-rw-r--r--static/images/symbol.pngbin58307 -> 0 bytes
23 files changed, 118 insertions, 56 deletions
diff --git a/.env.production b/.env.production
index 9bceaa7a..5f35a158 100644
--- a/.env.production
+++ b/.env.production
@@ -6,4 +6,5 @@ PUBLIC_LIQUID_EXPLORER=https://liquid.network
PUBLIC_DOMAIN=coinos.io
PUBLIC_COINOS_PUBKEY=ba80990666ef0b6f4ba5059347beb13242921e54669e680064ca755256a1e3a6
PUBLIC_COINOS_RELAY=wss://relay.coinos.io
-PUBLIC_COINOS_NETWORK=bitcoin \ No newline at end of file
+PUBLIC_COINOS_NETWORK=bitcoin
+PUBLIC_VAPID_PUBKEY=BEfgMDTeAn1F8ZQUGC6v5iKTD86zYXaa3QVr1E-ylKXC5c24JplcfSAN9PDlXAsVtUd3cU6j4-LsX_TKQzz_yDQ
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);
+ }
+ }),
+ );
});
diff --git a/static/images/badge.png b/static/images/badge.png
new file mode 100644
index 00000000..1cf21c9a
--- /dev/null
+++ b/static/images/badge.png
Binary files differ
diff --git a/static/images/icon-160.png b/static/images/icon-160.png
new file mode 100644
index 00000000..c2c74cea
--- /dev/null
+++ b/static/images/icon-160.png
Binary files differ
diff --git a/static/images/icon.png b/static/images/icon.png
new file mode 100644
index 00000000..330e73e5
--- /dev/null
+++ b/static/images/icon.png
Binary files differ
diff --git a/static/images/symbol.svg b/static/images/icon.svg
index d0c9e054..d0c9e054 100644
--- a/static/images/symbol.svg
+++ b/static/images/icon.svg
diff --git a/static/images/john.webp b/static/images/john.webp
deleted file mode 100644
index 7119e02c..00000000
--- a/static/images/john.webp
+++ /dev/null
Binary files differ
diff --git a/static/images/karnage.webp b/static/images/karnage.webp
deleted file mode 100644
index 5ba4eea1..00000000
--- a/static/images/karnage.webp
+++ /dev/null
Binary files differ
diff --git a/static/images/loft.jpg b/static/images/loft.jpg
deleted file mode 100644
index 39ca49ab..00000000
--- a/static/images/loft.jpg
+++ /dev/null
Binary files differ
diff --git a/static/images/moneypot.jpg b/static/images/moneypot.jpg
deleted file mode 100644
index 2084a99a..00000000
--- a/static/images/moneypot.jpg
+++ /dev/null
Binary files differ
diff --git a/static/images/moneypot.png b/static/images/moneypot.png
deleted file mode 100644
index b550ad98..00000000
--- a/static/images/moneypot.png
+++ /dev/null
Binary files differ
diff --git a/static/images/secondl1ght.webp b/static/images/secondl1ght.webp
deleted file mode 100644
index e4a93103..00000000
--- a/static/images/secondl1ght.webp
+++ /dev/null
Binary files differ
diff --git a/static/images/shauna.webp b/static/images/shauna.webp
deleted file mode 100644
index ee69b857..00000000
--- a/static/images/shauna.webp
+++ /dev/null
Binary files differ
diff --git a/static/images/symbol.png b/static/images/symbol.png
deleted file mode 100644
index 9f5acf73..00000000
--- a/static/images/symbol.png
+++ /dev/null
Binary files differ