diff options
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/lib/apiServer.js | 8 | ||||
| -rw-r--r-- | ui/lib/components/PushSubscription.svelte | 9 | ||||
| -rw-r--r-- | ui/routes/(app)/me/+page.svelte | 6 | ||||
| -rw-r--r-- | ui/routes/(swatch)/.swatch/+page.svelte | 1 | ||||
| -rw-r--r-- | ui/routes/(swatch)/.swatch/PushSubscription/+page.svelte | 79 | ||||
| -rw-r--r-- | ui/service-worker.js | 9 |
6 files changed, 106 insertions, 6 deletions
diff --git a/ui/lib/apiServer.js b/ui/lib/apiServer.js index f55f271..9eeb128 100644 --- a/ui/lib/apiServer.js +++ b/ui/lib/apiServer.js @@ -47,7 +47,7 @@ export async function getInvite(inviteId) { } export async function acceptInvite(inviteId, name, password) { - return apiServer + return await apiServer .post(`/invite/${inviteId}`, { name, password, @@ -56,7 +56,11 @@ export async function acceptInvite(inviteId, name, password) { } export async function createPushSubscription(subscription, vapid) { - return apiServer.post('/push/subscribe', { subscription, vapid }).catch(responseError); + return await apiServer.post('/push/subscribe', { subscription, vapid }).catch(responseError); +} + +export async function sendPing() { + return await apiServer.post('/push/ping', {}).catch(responseError); } export function subscribeToEvents(resumePoint) { diff --git a/ui/lib/components/PushSubscription.svelte b/ui/lib/components/PushSubscription.svelte index a85cbb3..aab4929 100644 --- a/ui/lib/components/PushSubscription.svelte +++ b/ui/lib/components/PushSubscription.svelte @@ -1,5 +1,5 @@ <script> - let { vapid, subscription, subscribe = async () => null } = $props(); + let { vapid, subscription, subscribe = async () => null, ping = async () => null } = $props(); let pending = $state(false); function onsubmit(callback) { @@ -16,12 +16,15 @@ } </script> -{#if vapid !== null} - {#if subscription === null} +{#if !!vapid} + {#if !subscription} <form class="form" onsubmit={onsubmit(subscribe)}> <button disabled={pending} type="submit">create push subscription</button> </form> {/if} + <form class="form" onsubmit={onsubmit(ping)}> + <button disabled={pending} type="submit">send test notification</button> + </form> {:else} Waiting for VAPID key… {/if} diff --git a/ui/routes/(app)/me/+page.svelte b/ui/routes/(app)/me/+page.svelte index ddb1245..a21d160 100644 --- a/ui/routes/(app)/me/+page.svelte +++ b/ui/routes/(app)/me/+page.svelte @@ -35,11 +35,15 @@ async function subscribe() { await session.push.subscribe(); } + + async function ping() { + await api.sendPing(); + } </script> <ChangePassword {changePassword} /> <hr /> -<PushSubscription {subscription} {vapid} {subscribe} /> +<PushSubscription {subscription} {vapid} {subscribe} {ping} /> <hr /> <Invites {invites} {createInvite} /> <hr /> diff --git a/ui/routes/(swatch)/.swatch/+page.svelte b/ui/routes/(swatch)/.swatch/+page.svelte index 5334438..c1969e5 100644 --- a/ui/routes/(swatch)/.swatch/+page.svelte +++ b/ui/routes/(swatch)/.swatch/+page.svelte @@ -19,5 +19,6 @@ <li><a href="MessageRun">MessageRun</a></li> <li><a href="MessageInput">MessageInput</a></li> <li><a href="Message">Message</a></li> + <li><a href="PushSubscription">PushSubscription</a></li> <li><a href="swatch/EventLog">swatch/EventLog</a></li> </ul> 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)} /> diff --git a/ui/service-worker.js b/ui/service-worker.js index d9b2a7c..cb32d0d 100644 --- a/ui/service-worker.js +++ b/ui/service-worker.js @@ -52,3 +52,12 @@ async function cacheFirst(request) { self.addEventListener('fetch', (event) => { event.respondWith(cacheFirst(event.request)); }); + +self.addEventListener('push', (event) => { + event.waitUntil( + self.registration.showNotification('Test notification', { + actions: [], + body: event.data.text(), + }), + ); +}); |
