import { useEffect, useState } from 'react'; import { useAtomValue } from 'jotai'; import { focusAssistActiveAtom } from '../state/focusAssist'; import { manualDndAtom } from '../state/manualDnd'; import { isSnoozeActive, notificationSnoozeUntilAtom } from '../state/notificationSnooze'; import { isWithinTimeWindow } from '../utils/timeWindow'; import { useSetting } from '../state/hooks/settings'; import { settingsAtom } from '../state/settings'; const QUIET_TICK_MS = 30_000; export type NotificationsQuietInputs = { focusAssistActive: boolean; manualDnd: boolean; snoozeUntil: number; quietHoursEnabled: boolean; quietHoursStart: string; quietHoursEnd: string; now?: Date; }; // Gitea #28 — pure "should we make noise right now?" predicate, extracted from // the gate that `ClientNonUIFeatures` already applies to message/invite sounds // (Focus Assist, manual tray DND, the snooze, and the quiet-hours window) so the // incoming-call ringtone (and anything else) can honour the same rules. export function isNotificationsQuiet({ focusAssistActive, manualDnd, snoozeUntil, quietHoursEnabled, quietHoursStart, quietHoursEnd, now, }: NotificationsQuietInputs): boolean { return ( focusAssistActive || manualDnd || isSnoozeActive(snoozeUntil, now?.getTime()) || (quietHoursEnabled && isWithinTimeWindow(quietHoursStart, quietHoursEnd, now)) ); } // Live-atoms/settings-backed version of `isNotificationsQuiet` for use in // components. export function useNotificationsQuiet(): boolean { // [Gitea #325] The quiet-hours window and the snooze expiry depend on the // clock, but the long-lived notifiers using this hook rarely re-render, so a // window starting (or a 30-minute pause ending) while the app stayed open was // never noticed. Re-evaluate on a tick, like the night-light overlay. const [, setTick] = useState(0); useEffect(() => { const id = setInterval(() => setTick((t) => t + 1), QUIET_TICK_MS); return () => clearInterval(id); }, []); const focusAssistActive = useAtomValue(focusAssistActiveAtom); const manualDnd = useAtomValue(manualDndAtom); const snoozeUntil = useAtomValue(notificationSnoozeUntilAtom); const [quietHoursEnabled] = useSetting(settingsAtom, 'quietHoursEnabled'); const [quietHoursStart] = useSetting(settingsAtom, 'quietHoursStart'); const [quietHoursEnd] = useSetting(settingsAtom, 'quietHoursEnd'); return isNotificationsQuiet({ focusAssistActive, manualDnd, snoozeUntil, quietHoursEnabled, quietHoursStart, quietHoursEnd, }); }