Files
pagerite/frontend/src/notify.js
T
LeoVasanko d3c89e8c66 Visitor contact messaging: in site communication system with email readiness (#3)
- `{contact}` or `{contact: Label}` to add a button on article, additional access on top right corner letter emoji
- Article button styling (with custom shape for Nitro theme)
- Visitor contact panel: live thread over the activity socket, rich composer (formatting,/file uploads), PoW anti-spam gating, contact email reveal after proof
- Admin inbox in the same overlay: thread list, replies, read marking, unread badge; background watch keeps badge and notifications live
- Messaging site settings (button label, email subject, our email) with per-language overrides and auto-translation support
- Browser notifications for new messages on both sides, with click-through to the new content
- Close conversation: archives the thread for admins, starts visitors fresh

Reviewed-on: https://git.zi.fi/LeoVasanko/pagerite/pulls/3
2026-09-29 03:01:00 +00:00

34 lines
1.4 KiB
JavaScript

// Browser notifications for contact messaging (docs/messages.md): the
// visitor is notified of admin replies, the admin of new visitor
// messages. Permission is requested at one entry point only — right
// after the first message of a fresh thread (the Notification API
// requires a user gesture). A denied permission is permanent in the
// browser, so we never re-ask; a dismissed prompt stays "default" and is
// asked again on the next fresh thread.
export function askNotifyPermission() {
if (!('Notification' in window) || Notification.permission !== 'default') return
Notification.requestPermission()
}
// Fire a notification (a no-op without a granted permission). Clicking
// it focuses the site tab and runs onclick (opening the thread/inbox
// view), so the user reliably lands on what was new.
export function notifyMessage(title, body, onclick) {
if (!('Notification' in window) || Notification.permission !== 'granted') return
const n = new Notification(title, { body, icon: '/favicon.ico' })
n.onclick = () => {
window.focus()
onclick?.()
n.close()
}
}
// The visible text of a server-rendered strict-markdown message (safe to
// parse: the stored html is markdown-it output, never user markup).
export function messageText(html) {
const div = document.createElement('div')
div.innerHTML = html
return (div.textContent || '').trim()
}