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
+51 -52
View File
@@ -21,9 +21,9 @@
* - EU DMA iOS 17.4+ caveat: PWA may open in Safari tabs; install guide addresses this.
*/
import { useState, useEffect } from 'react'
import { Smartphone, X } from 'lucide-react'
import { PushPermissionPrompt } from './PushPermissionPrompt.js'
import { useState, useEffect } from 'react';
import { Smartphone, X } from 'lucide-react';
import { PushPermissionPrompt } from './PushPermissionPrompt.js';
// ── iOS detection ──────────────────────────────────────────────────────────
@@ -38,12 +38,11 @@ import { PushPermissionPrompt } from './PushPermissionPrompt.js'
* 3. Check navigator.standalone is NOT true (standalone = already installed).
*/
export function isIOSSafariNonStandalone(): boolean {
const ua = navigator.userAgent
const ua = navigator.userAgent;
const isIOS =
/iPad|iPhone|iPod/.test(ua) &&
!(window as unknown as { MSStream?: unknown }).MSStream
const isStandalone = (navigator as unknown as { standalone?: boolean }).standalone === true
return isIOS && !isStandalone
/iPad|iPhone|iPod/.test(ua) && !(window as unknown as { MSStream?: unknown }).MSStream;
const isStandalone = (navigator as unknown as { standalone?: boolean }).standalone === true;
return isIOS && !isStandalone;
}
// ── Installed state check ──────────────────────────────────────────────────
@@ -56,14 +55,14 @@ function isInstalled(): boolean {
return (
window.matchMedia('(display-mode: standalone)').matches ||
(navigator as unknown as { standalone?: boolean }).standalone === true
)
);
}
// ── Android beforeinstallprompt hook ─────────────────────────────────────
interface BeforeInstallPromptEvent extends Event {
prompt(): Promise<void>
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>
prompt(): Promise<void>;
userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;
}
/**
@@ -75,40 +74,40 @@ interface BeforeInstallPromptEvent extends Event {
* triggerInstall: function that calls prompt() on the deferred event
*/
export function useAndroidInstallPrompt() {
const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(null)
const [deferredPrompt, setDeferredPrompt] = useState<BeforeInstallPromptEvent | null>(null);
// justInstalled: set to true when the appinstalled event fires, enabling the
// post-install push permission prompt trigger (D-08).
const [justInstalled, setJustInstalled] = useState(false)
const [justInstalled, setJustInstalled] = useState(false);
useEffect(() => {
const handler = (e: Event) => {
e.preventDefault()
setDeferredPrompt(e as BeforeInstallPromptEvent)
}
e.preventDefault();
setDeferredPrompt(e as BeforeInstallPromptEvent);
};
const installedHandler = () => {
setDeferredPrompt(null)
setJustInstalled(true)
}
setDeferredPrompt(null);
setJustInstalled(true);
};
window.addEventListener('beforeinstallprompt', handler)
window.addEventListener('appinstalled', installedHandler)
window.addEventListener('beforeinstallprompt', handler);
window.addEventListener('appinstalled', installedHandler);
return () => {
window.removeEventListener('beforeinstallprompt', handler)
window.removeEventListener('appinstalled', installedHandler)
}
}, [])
window.removeEventListener('beforeinstallprompt', handler);
window.removeEventListener('appinstalled', installedHandler);
};
}, []);
const triggerInstall = async () => {
if (!deferredPrompt) return
await deferredPrompt.prompt()
const { outcome } = await deferredPrompt.userChoice
if (!deferredPrompt) return;
await deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
if (outcome === 'accepted') {
setDeferredPrompt(null)
setDeferredPrompt(null);
}
}
};
return { canInstall: deferredPrompt !== null, triggerInstall, justInstalled }
return { canInstall: deferredPrompt !== null, triggerInstall, justInstalled };
}
// ── iOS Walkthrough Sheet ─────────────────────────────────────────────────
@@ -119,10 +118,10 @@ const IOS_STEPS = [
"Scroll down and tap 'Add to Home Screen'",
"Tap 'Add' in the top right",
'Open FamilySync from your Home Screen — it opens without the browser bar',
]
];
interface WalkthroughSheetProps {
onClose: () => void
onClose: () => void;
}
function WalkthroughSheet({ onClose }: WalkthroughSheetProps) {
@@ -142,7 +141,7 @@ function WalkthroughSheet({ onClose }: WalkthroughSheetProps) {
}}
onClick={(e) => {
// Close on backdrop click
if (e.target === e.currentTarget) onClose()
if (e.target === e.currentTarget) onClose();
}}
>
<div
@@ -272,7 +271,7 @@ function WalkthroughSheet({ onClose }: WalkthroughSheetProps) {
</button>
</div>
</div>
)
);
}
// ── InstallPrompt ─────────────────────────────────────────────────────────
@@ -290,44 +289,44 @@ function WalkthroughSheet({ onClose }: WalkthroughSheetProps) {
// degrades gracefully (treated as "not dismissed") instead of crashing the component.
function readDismissed(): boolean {
try {
return localStorage.getItem('installPromptDismissed') === '1'
return localStorage.getItem('installPromptDismissed') === '1';
} catch {
return false
return false;
}
}
function persistDismissed(): void {
try {
localStorage.setItem('installPromptDismissed', '1')
localStorage.setItem('installPromptDismissed', '1');
} catch {
// Ignore write failures (private mode / storage disabled)
}
}
export function InstallPrompt() {
const [dismissed, setDismissed] = useState<boolean>(readDismissed)
const [walkthroughOpen, setWalkthroughOpen] = useState(false)
const { canInstall, triggerInstall, justInstalled } = useAndroidInstallPrompt()
const [dismissed, setDismissed] = useState<boolean>(readDismissed);
const [walkthroughOpen, setWalkthroughOpen] = useState(false);
const { canInstall, triggerInstall, justInstalled } = useAndroidInstallPrompt();
// Re-check isInstalled on mount — matchMedia is only available in the browser
const [installed, setInstalled] = useState(false)
const [installed, setInstalled] = useState(false);
useEffect(() => {
setInstalled(isInstalled())
}, [])
setInstalled(isInstalled());
}, []);
// Show post-install permission prompt (D-08) immediately after the appinstalled event
// fires — before the page knows it is in standalone mode. This covers Android Chrome
// where the page stays loaded after install without a reload.
if (justInstalled) {
return <PushPermissionPrompt />
return <PushPermissionPrompt />;
}
// Nothing to show when already installed (App.tsx mounts PushPermissionPrompt there)
if (installed) return null
if (installed) return null;
function dismiss() {
persistDismissed()
setDismissed(true)
persistDismissed();
setDismissed(true);
}
// ── iOS banner ──────────────────────────────────────────────────────────
@@ -416,7 +415,7 @@ export function InstallPrompt() {
{walkthroughOpen && <WalkthroughSheet onClose={() => setWalkthroughOpen(false)} />}
</>
)
);
}
// ── Android banner ──────────────────────────────────────────────────────
@@ -458,7 +457,7 @@ export function InstallPrompt() {
{/* Install CTA */}
<button
onClick={() => {
void triggerInstall().then(() => dismiss())
void triggerInstall().then(() => dismiss());
}}
style={{
background: 'var(--color-text-primary, #111318)',
@@ -499,9 +498,9 @@ export function InstallPrompt() {
<X size={16} aria-hidden="true" />
</button>
</div>
)
);
}
// Nothing applicable — desktop, already installed, or dismissed
return null
return null;
}