mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-28 00:16:48 +09:00
Only room pages posted the subscription again, so a browser that changed its password and closed the profile page went without notifications until it next opened a room. A small controller in the layout does it now, still once per session, and the bell is back to how it was. Two tabs posting at once after a password change could both miss the row and insert two, so the endpoint is looked up again under the same write lock as the session check.
33 lines
1.4 KiB
JavaScript
33 lines
1.4 KiB
JavaScript
import { Controller } from "@hotwired/stimulus"
|
|
import { post } from "@rails/request.js"
|
|
|
|
const SYNCED_SESSION_KEY = "push-subscription-synced-session"
|
|
|
|
// A password change removes the account's push subscriptions, the one this browser holds included. Post it again
|
|
// once per session, so a browser that's still signed in keeps getting notifications. A failure here leaves the
|
|
// browser's own subscription alone: the next session tries again.
|
|
export default class extends Controller {
|
|
static values = { url: String, session: String }
|
|
|
|
async connect() {
|
|
if (this.#allowed && this.sessionValue && localStorage.getItem(SYNCED_SESSION_KEY) !== this.sessionValue) {
|
|
const registration = await navigator.serviceWorker.getRegistration(window.location.origin)
|
|
const subscription = await registration?.pushManager?.getSubscription()
|
|
|
|
if (Notification.permission === "granted" && subscription) {
|
|
await post(this.urlValue, { body: this.#payload(subscription), responseKind: "turbo-stream" })
|
|
localStorage.setItem(SYNCED_SESSION_KEY, this.sessionValue)
|
|
}
|
|
}
|
|
}
|
|
|
|
get #allowed() {
|
|
return navigator.serviceWorker && window.Notification
|
|
}
|
|
|
|
#payload(subscription) {
|
|
const { endpoint, keys: { p256dh, auth } } = subscription.toJSON()
|
|
return JSON.stringify({ push_subscription: { endpoint, p256dh_key: p256dh, auth_key: auth } })
|
|
}
|
|
}
|