42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
import { useEffect, useRef } from 'react'
|
|
import { getIsRemoteMode } from '../../bootstrap/state.js'
|
|
import {
|
|
type Notification,
|
|
useNotifications,
|
|
} from '../../context/notifications.js'
|
|
import { logError } from '../../utils/log.js'
|
|
|
|
type Result = Notification | Notification[] | null
|
|
|
|
/**
|
|
* Fires notification(s) once on mount. Encapsulates the remote-mode gate and
|
|
* once-per-session ref guard that was hand-rolled across 10+ notifs/ hooks.
|
|
*
|
|
* The compute fn runs exactly once on first effect. Return null to skip,
|
|
* a Notification to fire one, or an array to fire several. Sync or async.
|
|
* Rejections are routed to logError.
|
|
*/
|
|
export function useStartupNotification(
|
|
compute: () => Result | Promise<Result>,
|
|
): void {
|
|
const { addNotification } = useNotifications()
|
|
const hasRunRef = useRef(false)
|
|
const computeRef = useRef(compute)
|
|
computeRef.current = compute
|
|
|
|
useEffect(() => {
|
|
if (getIsRemoteMode() || hasRunRef.current) return
|
|
hasRunRef.current = true
|
|
|
|
void Promise.resolve()
|
|
.then(() => computeRef.current())
|
|
.then(result => {
|
|
if (!result) return
|
|
for (const n of Array.isArray(result) ? result : [result]) {
|
|
addNotification(n)
|
|
}
|
|
})
|
|
.catch(logError)
|
|
}, [addNotification])
|
|
}
|