mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-29 08:54:09 +09:00
Post the browser's push subscription from every page, and register it once
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.
From #371.
(cherry picked from commit 3786ee5244)
This commit is contained in:
1 parent
931f6b2c38
commit
fadf6f1859
7 files changed
+73
-35
No files matched your search
@@ -4,10 +4,8 @@ import { pageIsTurboPreview } from "helpers/turbo_helpers"
|
||||
import { onNextEventLoopTick } from "helpers/timing_helpers"
|
||||
import { getCookie, setCookie } from "lib/cookie"
|
||||
|
||||
const PUSH_SUBSCRIPTION_SYNCED_KEY = "push-subscription-synced-session"
|
||||
|
||||
export default class extends Controller {
|
||||
static values = { subscriptionsUrl: String, session: String }
|
||||
static values = { subscriptionsUrl: String }
|
||||
static targets = [ "notAllowedNotice", "bell", "details" ]
|
||||
static classes = [ "attention" ]
|
||||
|
||||
@@ -27,8 +25,6 @@ export default class extends Controller {
|
||||
this.#showBellAlert()
|
||||
}
|
||||
}
|
||||
|
||||
this.#resyncPushSubscriptionOncePerSession()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,21 +109,6 @@ export default class extends Controller {
|
||||
if (!response.ok) subscription.unsubscribe()
|
||||
}
|
||||
|
||||
// A password change removes the account's 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.
|
||||
async #resyncPushSubscriptionOncePerSession() {
|
||||
if (this.#allowed && this.sessionValue && localStorage.getItem(PUSH_SUBSCRIPTION_SYNCED_KEY) !== this.sessionValue) {
|
||||
const registration = await this.#serviceWorkerRegistration
|
||||
const subscription = await registration?.pushManager?.getSubscription()
|
||||
|
||||
if (Notification.permission === "granted" && subscription) {
|
||||
await post(this.subscriptionsUrlValue, { body: this.#extractJsonPayloadAsString(subscription), responseKind: "turbo-stream" })
|
||||
localStorage.setItem(PUSH_SUBSCRIPTION_SYNCED_KEY, this.sessionValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async #requestPermissionAndSubscribe(registration) {
|
||||
const permission = await Notification.requestPermission()
|
||||
if (permission === "granted") this.#subscribe(registration)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
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 } })
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user