fix: ui fixes
This commit is contained in:
+27
-1
@@ -110,10 +110,23 @@ export async function enablePush(): Promise<void> {
|
||||
throw new Error("Notification permission was not granted.");
|
||||
}
|
||||
|
||||
const reg = await navigator.serviceWorker.register("/sw.js");
|
||||
// The BFF origin rides along as a query param so the service worker can
|
||||
// re-register rotated subscriptions (pushsubscriptionchange) on its own.
|
||||
const reg = await navigator.serviceWorker.register(
|
||||
`/sw.js?bff=${encodeURIComponent(BFF_BASE)}`,
|
||||
);
|
||||
await navigator.serviceWorker.ready;
|
||||
|
||||
let sub = await reg.pushManager.getSubscription();
|
||||
// A subscription minted under a previous VAPID key still looks alive
|
||||
// locally, but every send fails with a credential mismatch — drop it and
|
||||
// subscribe fresh under the current key.
|
||||
if (sub && !matchesServerKey(sub, public_key)) {
|
||||
await sub.unsubscribe().catch(() => {
|
||||
/* stale anyway — subscribe() below replaces it */
|
||||
});
|
||||
sub = null;
|
||||
}
|
||||
if (!sub) {
|
||||
sub = await reg.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
@@ -134,6 +147,19 @@ export async function enablePush(): Promise<void> {
|
||||
if (!res.ok) throw new Error("Could not save your subscription.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether an existing subscription was created with the server's current
|
||||
* VAPID public key. Browsers that don't expose applicationServerKey (older
|
||||
* Safari) return null — treat that as a match rather than churn the sub.
|
||||
*/
|
||||
function matchesServerKey(sub: PushSubscription, publicKey: string): boolean {
|
||||
const current = sub.options?.applicationServerKey;
|
||||
if (!current) return true;
|
||||
const a = new Uint8Array(current);
|
||||
const b = urlBase64ToUint8Array(publicKey);
|
||||
return a.length === b.length && a.every((v, i) => v === b[i]);
|
||||
}
|
||||
|
||||
/** Disable push: unsubscribe locally and remove the subscription server-side. */
|
||||
export async function disablePush(): Promise<void> {
|
||||
const reg = await registration();
|
||||
|
||||
+2
-9
@@ -143,15 +143,8 @@ export const sadhna = {
|
||||
/** Acknowledge pending celebrations after showing the confetti. */
|
||||
ackRewards: () => call<void>("/sadhna/rewards/ack", { method: "POST" }),
|
||||
|
||||
/** Whether daily sādhana reminders are enabled for the caller. */
|
||||
reminderPrefs: () => call<{ enabled: boolean }>("/sadhna/reminders"),
|
||||
|
||||
/** Toggle daily sādhana reminders. */
|
||||
setReminderPrefs: (enabled: boolean) =>
|
||||
call<{ enabled: boolean }>("/sadhna/reminders", {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ enabled }),
|
||||
}),
|
||||
// Reminder prefs moved to the notification matrix —
|
||||
// see `notifications.prefs()` in lib/social.ts.
|
||||
|
||||
/** Report the browser's IANA timezone so reminders fire at local time. */
|
||||
setTimezone: (timezone: string) =>
|
||||
|
||||
+14
-6
@@ -505,18 +505,26 @@ export const notifications = {
|
||||
markAllRead() {
|
||||
return call<void>("/notifications/read", { method: "POST" });
|
||||
},
|
||||
/** Email-notification preferences (currently aggregated like emails). */
|
||||
emailPrefs() {
|
||||
return call<{ like_emails: boolean }>("/notifications/email-prefs");
|
||||
/** The event × channel notification matrix (Settings → Notifications). */
|
||||
prefs() {
|
||||
return call<{ prefs: NotificationPrefs }>("/notifications/prefs");
|
||||
},
|
||||
setEmailPrefs(likeEmails: boolean) {
|
||||
return call<{ like_emails: boolean }>("/notifications/email-prefs", {
|
||||
/** Write one matrix cell; returns the full re-resolved matrix. */
|
||||
setPref(event: PrefEvent, channel: PrefChannel, enabled: boolean) {
|
||||
return call<{ prefs: NotificationPrefs }>("/notifications/prefs", {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ like_emails: likeEmails }),
|
||||
body: JSON.stringify({ event, channel, enabled }),
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// ─── Notification preferences ──────────────────────────────────────────
|
||||
|
||||
export type PrefEvent = "follows" | "post_interactions" | "sadhna_reminders";
|
||||
export type PrefChannel = "in_app" | "email" | "push";
|
||||
/** event → channel → enabled, as resolved by the BFF (defaults on). */
|
||||
export type NotificationPrefs = Record<PrefEvent, Record<PrefChannel, boolean>>;
|
||||
|
||||
export const relationships = {
|
||||
/** Send a follow REQUEST. The target must accept before it counts as a
|
||||
* follow — the returned relationship reflects `follow_requested: true`
|
||||
|
||||
Reference in New Issue
Block a user