Save email notification prefs to app settings
Some checks failed
CI / lint-check-build (pull_request) Has been cancelled

This commit is contained in:
mplorentz 2026-08-27 15:08:37 -04:00
parent 5c027dd823
commit dd1182cb32
4 changed files with 72 additions and 8 deletions

View file

@ -1,4 +1,4 @@
import {hash, maybe} from "@welshman/lib" import {hash, maybe, throttle} from "@welshman/lib"
import type {Filter} from "@welshman/util" import type {Filter} from "@welshman/util"
import {Address, DELETE, makeEvent, makeHttpAuth, makeHttpAuthHeader} from "@welshman/util" import {Address, DELETE, makeEvent, makeHttpAuth, makeHttpAuthHeader} from "@welshman/util"
import {Relays, User} from "@welshman/app" import {Relays, User} from "@welshman/app"
@ -6,6 +6,7 @@ import {buildUrl} from "@lib/util"
import {app, thunks} from "@app/core" import {app, thunks} from "@app/core"
import {device} from "@app/device" import {device} from "@app/device"
import {EMAIL_NOTIFICATION_SERVER, PUSH_BRIDGE} from "@app/env" import {EMAIL_NOTIFICATION_SERVER, PUSH_BRIDGE} from "@app/env"
import {userSettingsValues} from "@app/settings"
import {emailNotificationState, syncRelaySubscriptions} from "@app/push/adapters/common" import {emailNotificationState, syncRelaySubscriptions} from "@app/push/adapters/common"
export class MailNotifications { export class MailNotifications {
@ -119,6 +120,32 @@ export class MailNotifications {
await this.unregister() await this.unregister()
} }
sync() {
return userSettingsValues.subscribe(
throttle(500, async ({email, emailAddress, emailFrequency}) => {
const current = emailNotificationState.get()
if (email && emailAddress) {
if (
!current.callback ||
current.email !== emailAddress ||
current.frequency !== emailFrequency
) {
try {
await this.register(emailAddress, emailFrequency)
} catch {
return
}
}
await this.enable()
} else {
await this.disable()
}
}),
)
}
_getSubscriptionIdentifier = (relay: string, key: string) => _getSubscriptionIdentifier = (relay: string, key: string) =>
String(hash(relay + key + device.get() + "email")) String(hash(relay + key + device.get() + "email"))

View file

@ -31,6 +31,9 @@ export type SettingsValues = {
font_size: number font_size: number
alerts: SpaceNotificationSettings[] alerts: SpaceNotificationSettings[]
zap_amounts: number[] zap_amounts: number[]
email: boolean
emailAddress: string
emailFrequency: string
} }
export const defaultSettings: SettingsValues = { export const defaultSettings: SettingsValues = {
@ -43,6 +46,9 @@ export const defaultSettings: SettingsValues = {
font_size: 1.1, font_size: 1.1,
alerts: [], alerts: [],
zap_amounts: [21, 210, 2100, 21000], zap_amounts: [21, 210, 2100, 21000],
email: false,
emailAddress: "",
emailFrequency: "daily",
} }
export class Settings extends DerivedPlugin<AppDataReader> { export class Settings extends DerivedPlugin<AppDataReader> {
@ -97,9 +103,6 @@ export const notificationSettings = withGetter(
spaces: true, spaces: true,
mentions: true, mentions: true,
messages: true, messages: true,
email: false,
emailFrequency: "daily",
emailAddress: "",
}), }),
) )

View file

@ -43,6 +43,7 @@
latestActivityByPath, latestActivityByPath,
} from "@app/notifications" } from "@app/notifications"
import {Push} from "@app/push" import {Push} from "@app/push"
import {Mail} from "@app/mail"
import {onPushNotificationAction, pushState} from "@app/push/adapters/common" import {onPushNotificationAction, pushState} from "@app/push/adapters/common"
import {syncKeyboard} from "@app/keyboard" import {syncKeyboard} from "@app/keyboard"
import {syncCallAudioResume} from "@app/call" import {syncCallAudioResume} from "@app/call"
@ -212,6 +213,9 @@
// Initialize background notifications // Initialize background notifications
unsubscribers.push(Push.sync()) unsubscribers.push(Push.sync())
// Sync email notification prefs across devices and register this device
unsubscribers.push(Mail.sync())
// Logging in swaps in a fresh app — its policies rebind themselves, we just have to sync // Logging in swaps in a fresh app — its policies rebind themselves, we just have to sync
// application data against the new identity's relays. Wait for the new app's storage to // application data against the new identity's relays. Wait for the new app's storage to
// load the way startup does, so sync reconciles against cached events. // load the way startup does, so sync reconciles against cached events.

View file

@ -15,7 +15,7 @@
import {clearBadges} from "@app/notifications" import {clearBadges} from "@app/notifications"
import {Push} from "@app/push" import {Push} from "@app/push"
import {Mail} from "@app/mail" import {Mail} from "@app/mail"
import {notificationSettings} from "@app/settings" import {notificationSettings, publishSettings, userSettingsValues} from "@app/settings"
import {emailNotificationState} from "@app/push/adapters/common" import {emailNotificationState} from "@app/push/adapters/common"
const clearError = () => { const clearError = () => {
@ -24,8 +24,24 @@
} }
} }
const buildSettings = () => {
const local = notificationSettings.get()
return {
push: local.push,
sound: local.sound,
badge: local.badge,
spaces: local.spaces,
mentions: local.mentions,
messages: local.messages,
email: $userSettingsValues.email,
emailAddress: $userSettingsValues.emailAddress,
emailFrequency: $userSettingsValues.emailFrequency,
}
}
const reset = () => { const reset = () => {
settings = {...notificationSettings.get()} settings = buildSettings()
clearError() clearError()
} }
@ -73,7 +89,21 @@
await Mail.disable() await Mail.disable()
} }
notificationSettings.set(settings) // Sync email prefs across devices via AppData
await publishSettings({
email: settings.email,
emailAddress: settings.emailAddress,
emailFrequency: settings.emailFrequency,
})
notificationSettings.set({
push: settings.push,
sound: settings.sound,
badge: settings.badge,
spaces: settings.spaces,
mentions: settings.mentions,
messages: settings.messages,
})
pushToast({message: "Your settings have been saved!"}) pushToast({message: "Your settings have been saved!"})
} finally { } finally {
@ -82,7 +112,7 @@
}) })
let loading = $state(false) let loading = $state(false)
let settings = $state({...notificationSettings.get()}) let settings = $state(buildSettings())
</script> </script>
<form {onsubmit}> <form {onsubmit}>