From 18a383edab696f95af3f075d80e7ebb911661bd8 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Thu, 19 Jun 2025 10:01:16 -0700 Subject: [PATCH] Update alert form to include push notifications --- src/app/commands.ts | 52 +++++++++++++++++--- src/app/components/AlertAdd.svelte | 74 ++++++++++++++++++++--------- src/app/components/MenuSpace.svelte | 31 ++++++++++-- src/app/requests.ts | 7 +-- src/app/state.ts | 9 ++-- src/assets/icons/Bell.svg | 4 ++ src/lib/components/Icon.svelte | 2 + 7 files changed, 138 insertions(+), 41 deletions(-) create mode 100644 src/assets/icons/Bell.svg diff --git a/src/app/commands.ts b/src/app/commands.ts index 8127183..14ff37e 100644 --- a/src/app/commands.ts +++ b/src/app/commands.ts @@ -14,6 +14,8 @@ import { AUTH_JOIN, ROOMS, COMMENT, + ALERT_REQUEST_PUSH, + ALERT_REQUEST_EMAIL, isSignedEvent, makeEvent, displayProfile, @@ -54,7 +56,6 @@ import { PROTECTED, userMembership, INDEXER_RELAYS, - ALERT, NOTIFIER_PUBKEY, NOTIFIER_RELAY, userRoomsByUrl, @@ -368,7 +369,7 @@ export const makeComment = ({event, content, tags = []}: CommentParams) => export const publishComment = ({relays, ...params}: CommentParams & {relays: string[]}) => publishThunk({event: makeComment(params), relays}) -export type AlertParams = { +export type EmailAlertParams = { feed: Feed cron: string email: string @@ -376,7 +377,13 @@ export type AlertParams = { claims: Record } -export const makeAlert = async ({cron, email, feed, claims, description}: AlertParams) => { +export const makeEmailAlert = async ({ + cron, + email, + feed, + claims, + description, +}: EmailAlertParams) => { const tags = [ ["feed", JSON.stringify(feed)], ["cron", cron], @@ -384,7 +391,6 @@ export const makeAlert = async ({cron, email, feed, claims, description}: AlertP ["locale", LOCALE], ["timezone", TIMEZONE], ["description", description], - ["channel", "email"], [ "handler", "31990:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1737058597050", @@ -397,7 +403,7 @@ export const makeAlert = async ({cron, email, feed, claims, description}: AlertP tags.push(["claim", relay, claim]) } - return makeEvent(ALERT, { + return makeEvent(ALERT_REQUEST_EMAIL, { content: await signer.get().nip44.encrypt(NOTIFIER_PUBKEY, JSON.stringify(tags)), tags: [ ["d", randomId()], @@ -406,5 +412,37 @@ export const makeAlert = async ({cron, email, feed, claims, description}: AlertP }) } -export const publishAlert = async (params: AlertParams) => - publishThunk({event: await makeAlert(params), relays: [NOTIFIER_RELAY]}) +export const publishEmailAlert = async (params: EmailAlertParams) => + publishThunk({event: await makeEmailAlert(params), relays: [NOTIFIER_RELAY]}) + +export type PushAlertParams = { + feed: Feed + description: string + claims: Record +} + +export const makePushAlert = async ({feed, claims, description}: PushAlertParams) => { + const tags = [ + ["feed", JSON.stringify(feed)], + ["locale", LOCALE], + ["timezone", TIMEZONE], + ["description", description], + ["token", ""], + ["platform", ""], + ] + + for (const [relay, claim] of Object.entries(claims)) { + tags.push(["claim", relay, claim]) + } + + return makeEvent(ALERT_REQUEST_PUSH, { + content: await signer.get().nip44.encrypt(NOTIFIER_PUBKEY, JSON.stringify(tags)), + tags: [ + ["d", randomId()], + ["p", NOTIFIER_PUBKEY], + ], + }) +} + +export const publishPushAlert = async (params: PushAlertParams) => + publishThunk({event: await makePushAlert(params), relays: [NOTIFIER_RELAY]}) diff --git a/src/app/components/AlertAdd.svelte b/src/app/components/AlertAdd.svelte index fdb9b18..ffad1be 100644 --- a/src/app/components/AlertAdd.svelte +++ b/src/app/components/AlertAdd.svelte @@ -13,22 +13,34 @@ import ModalFooter from "@lib/components/ModalFooter.svelte" import {alerts, getMembershipUrls, getMembershipRoomsByUrl, userMembership} from "@app/state" import {loadAlertStatuses, requestRelayClaims} from "@app/requests" - import {publishAlert} from "@app/commands" + import {publishEmailAlert, publishPushAlert} from "@app/commands" import {pushToast} from "@app/toast" + type Props = { + channel?: string + relay?: string + notifyChat?: boolean + notifyThreads?: boolean + notifyCalendar?: boolean + } + + let { + relay = "", + channel = "email", + notifyChat = true, + notifyThreads = true, + notifyCalendar = true, + }: Props = $props() + const timezoneOffset = parseInt(TIMEZONE.slice(3)) / 100 const minute = randomInt(0, 59) const hour = (17 - timezoneOffset) % 24 const WEEKLY = `0 ${minute} ${hour} * * 1` const DAILY = `0 ${minute} ${hour} * * *` - let loading = false - let cron = WEEKLY - let email = $alerts.map(a => getTagValue("email", a.tags)).filter(identity)[0] || "" - let relay = "" - let notifyThreads = true - let notifyCalendar = true - let notifyChat = false + let loading = $state(false) + let cron = $state(WEEKLY) + let email = $state($alerts.map(a => getTagValue("email", a.tags)).filter(identity)[0] || "") const back = () => history.back() @@ -84,7 +96,10 @@ const cadence = cron?.endsWith("1") ? "Weekly" : "Daily" const description = `${cadence} alert for ${displayList(display)} on ${displayRelayUrl(relay)}, sent via email.` const feed = makeIntersectionFeed(feedFromFilters(filters), makeRelayFeed(relay)) - const thunk = await publishAlert({cron, email, feed, claims, description}) + const thunk = + channel === "email" + ? await publishEmailAlert({cron, email, feed, claims, description}) + : await publishPushAlert({feed, claims, description}) await thunk.result await loadAlertStatuses($pubkey!) @@ -105,25 +120,38 @@ {#snippet label()} -

Email Address*

+

Alert Type*

{/snippet} {#snippet input()} - - {/snippet} -
- - {#snippet label()} -

Frequency*

- {/snippet} - {#snippet input()} - + + {/snippet}
+ {#if channel === "email"} + + {#snippet label()} +

Email Address*

+ {/snippet} + {#snippet input()} + + {/snippet} +
+ + {#snippet label()} +

Frequency*

+ {/snippet} + {#snippet input()} + + {/snippet} +
+ {/if} {#snippet label()}

Space*

diff --git a/src/app/components/MenuSpace.svelte b/src/app/components/MenuSpace.svelte index 4fbdf41..6ad9fa6 100644 --- a/src/app/components/MenuSpace.svelte +++ b/src/app/components/MenuSpace.svelte @@ -1,7 +1,7 @@ @@ -86,7 +96,7 @@