2026-03-19 15:32:32 +00:00
|
|
|
import type {Unsubscriber} from "svelte/store"
|
2026-09-09 01:31:37 +00:00
|
|
|
import {ellipsize, maybe} from "@welshman/lib"
|
2026-07-28 16:16:26 +00:00
|
|
|
import {hexTags, matchFilter, tagValues, type TrustedEvent} from "@welshman/util"
|
2026-06-08 22:33:38 +00:00
|
|
|
import {DM_KINDS} from "@app/content"
|
2026-07-28 16:16:26 +00:00
|
|
|
import {app} from "@app/core"
|
2026-06-08 22:33:38 +00:00
|
|
|
import {notificationSettings} from "@app/settings"
|
2026-06-08 21:14:40 +00:00
|
|
|
import type {IPushAdapter} from "@app/push/adapters/common"
|
|
|
|
|
import {onNotification} from "@app/push/adapters/common"
|
2026-09-09 16:59:54 +00:00
|
|
|
import {renderEventAsSummary} from "@app/render"
|
2026-06-08 21:14:40 +00:00
|
|
|
import {goToEvent} from "@app/routes"
|
2026-03-19 15:32:32 +00:00
|
|
|
|
2026-09-09 01:31:37 +00:00
|
|
|
const PREVIEW_LENGTH = 120
|
|
|
|
|
|
2026-03-19 15:32:32 +00:00
|
|
|
export class WebNotifications implements IPushAdapter {
|
|
|
|
|
_unsubscriber = maybe<Unsubscriber>()
|
|
|
|
|
|
|
|
|
|
async request(prompt = true) {
|
|
|
|
|
if (prompt && Notification?.permission === "default") {
|
|
|
|
|
await Notification.requestPermission()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Notification?.permission || "denied"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_notify(event: TrustedEvent, title: string, body: string) {
|
|
|
|
|
const notification = new Notification(title, {
|
|
|
|
|
body,
|
|
|
|
|
tag: event.id,
|
|
|
|
|
icon: "/icon.png",
|
|
|
|
|
badge: "/icon.png",
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
notification.onclick = () => {
|
|
|
|
|
window.focus()
|
|
|
|
|
goToEvent(event)
|
|
|
|
|
notification.close()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onVisibilityChange = () => {
|
|
|
|
|
if (document.visibilityState === "visible") {
|
|
|
|
|
notification.close()
|
|
|
|
|
document.removeEventListener("visibilitychange", onVisibilityChange)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.addEventListener("visibilitychange", onVisibilityChange)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async enable() {
|
|
|
|
|
if (!this._unsubscriber) {
|
|
|
|
|
this._unsubscriber = onNotification(event => {
|
|
|
|
|
const {push, messages, mentions, spaces} = notificationSettings.get()
|
2026-07-28 16:16:26 +00:00
|
|
|
const $pubkey = app.get().user?.pubkey
|
2026-03-19 15:32:32 +00:00
|
|
|
|
|
|
|
|
if (push && document.hidden && Notification?.permission === "granted") {
|
2026-09-09 16:59:54 +00:00
|
|
|
const preview = ellipsize(renderEventAsSummary(event), PREVIEW_LENGTH, "…")
|
2026-09-09 01:31:37 +00:00
|
|
|
|
2026-03-19 15:32:32 +00:00
|
|
|
if (messages && matchFilter({kinds: DM_KINDS}, event)) {
|
2026-09-09 01:31:37 +00:00
|
|
|
this._notify(
|
|
|
|
|
event,
|
|
|
|
|
"New direct message",
|
|
|
|
|
preview || "Someone sent you a direct message.",
|
|
|
|
|
)
|
2026-07-28 16:16:26 +00:00
|
|
|
} else if (mentions && $pubkey && tagValues(hexTags("p"), event.tags).includes($pubkey)) {
|
2026-09-09 01:31:37 +00:00
|
|
|
this._notify(
|
|
|
|
|
event,
|
|
|
|
|
"Someone mentioned you",
|
|
|
|
|
preview || "Someone tagged you in a message.",
|
|
|
|
|
)
|
2026-03-19 15:32:32 +00:00
|
|
|
} else if (spaces) {
|
2026-09-09 01:31:37 +00:00
|
|
|
this._notify(event, "New activity", preview || "Someone posted a new message.")
|
2026-03-19 15:32:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async disable() {
|
|
|
|
|
this._unsubscriber?.()
|
|
|
|
|
this._unsubscriber = undefined
|
|
|
|
|
}
|
|
|
|
|
}
|