diff --git a/components/TimerWidget.tsx b/components/TimerWidget.tsx index d78ce2a..b911d67 100644 --- a/components/TimerWidget.tsx +++ b/components/TimerWidget.tsx @@ -120,21 +120,27 @@ export default function TimerWidget() { }, [timers, tick]) const dismissTimer = async (id: string) => { + firedRef.current.delete(id) + setFiredIds(new Set(firedRef.current)) + setTimers(ts => ts.filter(t => t.id !== id)) try { - firedRef.current.delete(id) - setFiredIds(new Set(firedRef.current)) - // We use POST with bearer — but widget runs with cookie auth. - // Cancel endpoint only accepts bearer; for user-dismissal we use DELETE-style via... hmm. - // For simplicity, tell server to cancel via a plain GET-less POST flow — skip server call here. - // (The timer will be cleaned up on next listActive when expired >30min ago.) - setTimers(ts => ts.filter(t => t.id !== id)) + // Fire-and-forget server cancel. API теперь принимает cookie auth, так что + // браузерный запрос проходит middleware. + await fetch('/api/voice/timer', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ action: 'cancel', id }), + credentials: 'include', + }) } catch {} } const now = Date.now() const active = timers.filter(t => { const remain = new Date(t.endsAt).getTime() - now - return remain > -30 * 60 * 1000 // keep expired ones visible for 30 min max + // Keep expired for only 30 sec — иначе при перезагрузке давно прошедший + // таймер снова начнёт трезвонить. + return remain > -30 * 1000 }) if (active.length === 0) return null diff --git a/lib/timers.ts b/lib/timers.ts index 6392315..fe29f6e 100644 --- a/lib/timers.ts +++ b/lib/timers.ts @@ -28,8 +28,10 @@ function save(list: Timer[]) { } function cleanup(list: Timer[]): Timer[] { - // Drop items expired more than 30 min ago - const cutoff = Date.now() - 30 * 60 * 1000 + // Drop items expired more than 30 seconds ago. Достаточно чтобы показать + // «звенит» при активной странице, но не воскрешать alarm после перезагрузки + // через час. + const cutoff = Date.now() - 30 * 1000 return list.filter(t => new Date(t.endsAt).getTime() > cutoff) }