summaryrefslogtreecommitdiff
path: root/ui/routes/(swatch)/.swatch/PushSubscription
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2025-11-08 16:28:10 -0500
committerOwen Jacobson <owen@grimoire.ca>2025-11-08 16:28:10 -0500
commitfc6914831743f6d683c59adb367479defe6f8b3a (patch)
tree5b997adac55f47b52f30022013b8ec3b2c10bcc5 /ui/routes/(swatch)/.swatch/PushSubscription
parent0ef69c7d256380e660edc45ace7f1d6151226340 (diff)
parent6bab5b4405c9adafb2ce76540595a62eea80acc0 (diff)
Integrate the prototype push notification support.
We're going to move forwards with this for now, as low-utility as it is, so that we can more easily iterate on it in a real-world environment (hi.grimoire.ca).
Diffstat (limited to 'ui/routes/(swatch)/.swatch/PushSubscription')
-rw-r--r--ui/routes/(swatch)/.swatch/PushSubscription/+page.svelte79
1 files changed, 79 insertions, 0 deletions
diff --git a/ui/routes/(swatch)/.swatch/PushSubscription/+page.svelte b/ui/routes/(swatch)/.swatch/PushSubscription/+page.svelte
new file mode 100644
index 0000000..3d564a3
--- /dev/null
+++ b/ui/routes/(swatch)/.swatch/PushSubscription/+page.svelte
@@ -0,0 +1,79 @@
+<script>
+ import { DateTime } from 'luxon';
+
+ import PushSubscription from '$lib/components/PushSubscription.svelte';
+ import { makeDeriver } from '$lib/swatch/derive.js';
+ import EventLog from '$lib/components/swatch/EventLog.svelte';
+ import EventCapture from '$lib/swatch/event-capture.svelte.js';
+ import * as json from '$lib/swatch/json.js';
+
+ function fromBase64(str) {
+ if (str.trim().length === 0) {
+ return null;
+ }
+ const bytes = Uint8Array.fromBase64(str, { alphabet: 'base64url' });
+ return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
+ }
+
+ const base64Deriver = makeDeriver(fromBase64);
+
+ // This is a "real" key, but it's not a key that's in use anywhere. I generated it for this
+ // purpose. -o
+ const testVapidKey =
+ 'BJXUH-WxM8BoxntTsrLufxc2Zlbwk-A1wsF01-ykUyh9pSUZG1Ymk3R-FOxJTGApQeJWIYTW9j-1sLQFIL8cGBU=';
+
+ let vapidInput = $state('');
+ let vapid = $derived(base64Deriver(vapidInput));
+
+ // See <> for schema. This is an approximation of the browser subscription object.
+ const testSubscription = json.encode({
+ endpoint: 'https://push.example.com/1234',
+ expirationTime: performance.now() + 86400 /* sec */ * 1000 /* millisec */,
+ options: {
+ userVisibleOnly: true,
+ applicationServerKey: null,
+ },
+ });
+
+ let subscriptionInput = $state('');
+ let subscription = $derived(json.decode(subscriptionInput));
+
+ let capture = $state(new EventCapture());
+ const subscribe = capture.on('subscribe');
+ const ping = capture.on('ping');
+</script>
+
+<h1><code>PushSubscription</code></h1>
+
+<nav><p><a href=".">Back to swatches</a></p></nav>
+
+<h2>properties</h2>
+
+<div class="component-properties">
+ <label>vapid key <input type="text" bind:value={vapidInput} /></label>
+ <div class="suggestion">
+ interesting values:
+ <button onclick={() => (vapidInput = '')}>(none)</button>
+ <button onclick={() => (vapidInput = testVapidKey)}>test key</button>
+ </div>
+
+ <label
+ ><p>subscription (json)</p>
+ <textarea bind:value={subscriptionInput}></textarea>
+ <div class="suggestion">
+ interesting values:
+ <button onclick={() => (subscriptionInput = '')}>(none)</button>
+ <button onclick={() => (subscriptionInput = testSubscription)}>example</button>
+ </div>
+ </label>
+</div>
+
+<h2>rendered</h2>
+
+<div class="component-preview">
+ <PushSubscription {vapid} {subscription} {subscribe} {ping} />
+</div>
+
+<h2>events</h2>
+
+<EventLog events={capture.events} clear={capture.clear.bind(capture)} />