style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
+79 -79
View File
@@ -30,7 +30,7 @@
* setEnabled(false) — unsubscribe + set '0'.
*/
import { useState, useEffect } from 'react'
import { useState, useEffect } from 'react';
// ---------------------------------------------------------------------------
// Helpers
@@ -42,15 +42,15 @@ import { useState, useEffect } from 'react'
* applicationServerKey (Web Push spec — key must be a BufferSource).
*/
function urlBase64ToUint8Array(base64String: string): Uint8Array<ArrayBuffer> {
const padding = '='.repeat((4 - (base64String.length % 4)) % 4)
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/')
const rawData = atob(base64)
const buffer = new ArrayBuffer(rawData.length)
const outputArray = new Uint8Array(buffer)
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = atob(base64);
const buffer = new ArrayBuffer(rawData.length);
const outputArray = new Uint8Array(buffer);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i)
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray
return outputArray;
}
/**
@@ -59,18 +59,18 @@ function urlBase64ToUint8Array(base64String: string): Uint8Array<ArrayBuffer> {
* are instant — the tap handler can proceed without an extra round-trip.
*/
async function fetchVapidKey(): Promise<string> {
const cached = sessionStorage.getItem('vapidPublicKey')
if (cached) return cached
const cached = sessionStorage.getItem('vapidPublicKey');
if (cached) return cached;
const res = await fetch('/api/push/vapid-public-key', {
credentials: 'include',
})
if (!res.ok) throw new Error(`Failed to fetch VAPID key: ${res.status}`)
const data = (await res.json()) as { publicKey: string }
});
if (!res.ok) throw new Error(`Failed to fetch VAPID key: ${res.status}`);
const data = (await res.json()) as { publicKey: string };
if (data.publicKey) {
sessionStorage.setItem('vapidPublicKey', data.publicKey)
sessionStorage.setItem('vapidPublicKey', data.publicKey);
}
return data.publicKey
return data.publicKey;
}
// ---------------------------------------------------------------------------
@@ -79,9 +79,9 @@ async function fetchVapidKey(): Promise<string> {
function readNotificationsEnabled(): boolean {
try {
return localStorage.getItem('notificationsEnabled') === '1'
return localStorage.getItem('notificationsEnabled') === '1';
} catch {
return false
return false;
}
}
@@ -91,18 +91,18 @@ function readNotificationsEnabled(): boolean {
*/
function readNotificationsDisabled(): boolean {
try {
return localStorage.getItem('notificationsEnabled') === '0'
return localStorage.getItem('notificationsEnabled') === '0';
} catch {
return false
return false;
}
}
function persistNotificationsEnabled(value: boolean): void {
try {
if (value) {
localStorage.setItem('notificationsEnabled', '1')
localStorage.setItem('notificationsEnabled', '1');
} else {
localStorage.setItem('notificationsEnabled', '0')
localStorage.setItem('notificationsEnabled', '0');
}
} catch {
// Private mode / storage disabled — ignore
@@ -121,12 +121,12 @@ export interface UsePushSubscriptionReturn {
* in a useEffect) and passed in here. This eliminates the network round-trip inside
* the tap handler, preserving the iOS user-gesture requirement for pushManager.subscribe().
*/
subscribe: (registration: ServiceWorkerRegistration, vapidKey: string) => Promise<void>
unsubscribe: () => Promise<void>
subscribe: (registration: ServiceWorkerRegistration, vapidKey: string) => Promise<void>;
unsubscribe: () => Promise<void>;
/** Current Notification.permission value ('default' | 'granted' | 'denied') */
permission: NotificationPermission
permission: NotificationPermission;
/** True when an active push subscription exists in pushManager. */
isSubscribed: boolean
isSubscribed: boolean;
/**
* Master on/off toggle (D-09).
*
@@ -138,27 +138,27 @@ export interface UsePushSubscriptionReturn {
* setEnabled(false):
* - Calls unsubscribe() (DELETE server + browser) + persists '0'.
*/
setEnabled: (on: boolean) => Promise<void>
setEnabled: (on: boolean) => Promise<void>;
}
export function usePushSubscription(): UsePushSubscriptionReturn {
const [permission, setPermission] = useState<NotificationPermission>(
typeof Notification !== 'undefined' ? Notification.permission : 'default',
)
const [isSubscribed, setIsSubscribed] = useState(false)
);
const [isSubscribed, setIsSubscribed] = useState(false);
// Health-check on mount (D-10): if OS permission is granted but no active
// subscription exists (expired/cleared) AND user hasn't explicitly disabled,
// silently re-subscribe in background.
useEffect(() => {
if (typeof Notification === 'undefined') return
if (Notification.permission !== 'granted') return
if (!navigator.serviceWorker) return
if (typeof Notification === 'undefined') return;
if (Notification.permission !== 'granted') return;
if (!navigator.serviceWorker) return;
void (async () => {
try {
const registration = await navigator.serviceWorker.ready
const existingSub = await registration.pushManager.getSubscription()
const registration = await navigator.serviceWorker.ready;
const existingSub = await registration.pushManager.getSubscription();
if (existingSub) {
// Re-confirm server-side record (handles 410-prune recovery — D-10).
@@ -168,33 +168,33 @@ export function usePushSubscription(): UsePushSubscriptionReturn {
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(existingSub.toJSON()),
}).catch(() => {}) // non-blocking — ignore network failures
setIsSubscribed(true)
return
}).catch(() => {}); // non-blocking — ignore network failures
setIsSubscribed(true);
return;
}
// No active subscription — only silently re-subscribe if the user
// hasn't explicitly turned notifications off (D-10).
if (readNotificationsDisabled()) return
if (readNotificationsDisabled()) return;
const vapidKey = await fetchVapidKey()
const vapidKey = await fetchVapidKey();
const sub = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidKey),
})
});
await fetch('/api/push/subscription', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(sub.toJSON()),
})
persistNotificationsEnabled(true)
setIsSubscribed(true)
});
persistNotificationsEnabled(true);
setIsSubscribed(true);
} catch {
// Ignore health-check errors — non-blocking background task
}
})()
}, [])
})();
}, []);
/**
* subscribe — MUST be called inside an onClick handler.
@@ -219,7 +219,7 @@ export function usePushSubscription(): UsePushSubscriptionReturn {
const sub = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidKey),
})
});
// Persist the subscription to the server
const res = await fetch('/api/push/subscription', {
@@ -227,39 +227,39 @@ export function usePushSubscription(): UsePushSubscriptionReturn {
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(sub.toJSON()),
})
});
if (!res.ok) {
throw new Error(`Failed to persist subscription: ${res.status}`)
throw new Error(`Failed to persist subscription: ${res.status}`);
}
persistNotificationsEnabled(true)
setPermission(Notification.permission)
setIsSubscribed(true)
}
persistNotificationsEnabled(true);
setPermission(Notification.permission);
setIsSubscribed(true);
};
/**
* unsubscribe — retrieve the active subscription and cancel it.
* Also removes the server-side row via DELETE /api/push/subscription.
*/
const unsubscribe = async (): Promise<void> => {
if (!navigator.serviceWorker) return
if (!navigator.serviceWorker) return;
const registration = await navigator.serviceWorker.ready
const sub = await registration.pushManager.getSubscription()
const registration = await navigator.serviceWorker.ready;
const sub = await registration.pushManager.getSubscription();
if (sub) {
await sub.unsubscribe()
await sub.unsubscribe();
}
await fetch('/api/push/subscription', {
method: 'DELETE',
credentials: 'include',
})
});
persistNotificationsEnabled(false)
setPermission(Notification.permission)
setIsSubscribed(false)
}
persistNotificationsEnabled(false);
setPermission(Notification.permission);
setIsSubscribed(false);
};
/**
* setEnabled — master on/off for the settings toggle (D-09).
@@ -271,52 +271,52 @@ export function usePushSubscription(): UsePushSubscriptionReturn {
*/
const setEnabled = async (on: boolean): Promise<void> => {
if (!on) {
await unsubscribe()
return
await unsubscribe();
return;
}
// on=true path
const currentPermission =
typeof Notification !== 'undefined' ? Notification.permission : 'default'
typeof Notification !== 'undefined' ? Notification.permission : 'default';
if (currentPermission !== 'granted') {
// 'default' → caller must use tap-gated subscribe(); 'denied' → no-op
return
return;
}
// Permission is granted — silently subscribe without a tap gesture
// (already have OS permission, no dialog required).
if (!navigator.serviceWorker) return
if (!navigator.serviceWorker) return;
try {
const registration = await navigator.serviceWorker.ready
const existingSub = await registration.pushManager.getSubscription()
const registration = await navigator.serviceWorker.ready;
const existingSub = await registration.pushManager.getSubscription();
if (existingSub) {
// Already subscribed — just flip the stored flag back on.
persistNotificationsEnabled(true)
setIsSubscribed(true)
return
persistNotificationsEnabled(true);
setIsSubscribed(true);
return;
}
const vapidKey = await fetchVapidKey()
const vapidKey = await fetchVapidKey();
const sub = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidKey),
})
});
const res = await fetch('/api/push/subscription', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(sub.toJSON()),
})
});
if (res.ok) {
persistNotificationsEnabled(true)
setIsSubscribed(true)
persistNotificationsEnabled(true);
setIsSubscribed(true);
}
} catch {
// Ignore — non-fatal; user can retry via toggle
}
}
};
return { subscribe, unsubscribe, permission, isSubscribed, setEnabled }
return { subscribe, unsubscribe, permission, isSubscribed, setEnabled };
}
/**
@@ -326,7 +326,7 @@ export function usePushSubscription(): UsePushSubscriptionReturn {
*/
export async function prefetchVapidKey(): Promise<void> {
try {
await fetchVapidKey()
await fetchVapidKey();
} catch {
// Non-fatal — the subscribe() call will retry if sessionStorage miss
}
@@ -337,4 +337,4 @@ export async function prefetchVapidKey(): Promise<void> {
* (localStorage.notificationsEnabled === '1').
* Exported for use in PermissionDeniedBanner and SettingsSheet initial state.
*/
export { readNotificationsEnabled }
export { readNotificationsEnabled };