fix(03): IN-03 guard localStorage access in InstallPrompt

This commit is contained in:
Lucas Berger
2026-06-09 10:43:37 -04:00
parent e29d6c1714
commit 7e4ea710d0
+21 -4
View File
@@ -278,10 +278,27 @@ function WalkthroughSheet({ onClose }: WalkthroughSheetProps) {
* *
* Mount this at the top level of CalendarShell, below the nav bar. * Mount this at the top level of CalendarShell, below the nav bar.
*/ */
// IN-03: localStorage access is guarded — in private-mode / SSR contexts the API can
// throw on read or write. Mirrors calendarStore.ts's pattern so a storage failure
// degrades gracefully (treated as "not dismissed") instead of crashing the component.
function readDismissed(): boolean {
try {
return localStorage.getItem('installPromptDismissed') === '1'
} catch {
return false
}
}
function persistDismissed(): void {
try {
localStorage.setItem('installPromptDismissed', '1')
} catch {
// Ignore write failures (private mode / storage disabled)
}
}
export function InstallPrompt() { export function InstallPrompt() {
const [dismissed, setDismissed] = useState<boolean>( const [dismissed, setDismissed] = useState<boolean>(readDismissed)
() => localStorage.getItem('installPromptDismissed') === '1',
)
const [walkthroughOpen, setWalkthroughOpen] = useState(false) const [walkthroughOpen, setWalkthroughOpen] = useState(false)
const { canInstall, triggerInstall } = useAndroidInstallPrompt() const { canInstall, triggerInstall } = useAndroidInstallPrompt()
@@ -295,7 +312,7 @@ export function InstallPrompt() {
if (installed) return null if (installed) return null
function dismiss() { function dismiss() {
localStorage.setItem('installPromptDismissed', '1') persistDismissed()
setDismissed(true) setDismissed(true)
} }