forked from liuup/claude-code-analysis
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseNotifyAfterTimeout.ts
More file actions
65 lines (57 loc) · 2.41 KB
/
useNotifyAfterTimeout.ts
File metadata and controls
65 lines (57 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { useEffect } from 'react'
import {
getLastInteractionTime,
updateLastInteractionTime,
} from '../bootstrap/state.js'
import { useTerminalNotification } from '../ink/useTerminalNotification.js'
import { sendNotification } from '../services/notifier.js'
// The time threshold in milliseconds for considering an interaction "recent" (6 seconds)
export const DEFAULT_INTERACTION_THRESHOLD_MS = 6000
function getTimeSinceLastInteraction(): number {
return Date.now() - getLastInteractionTime()
}
function hasRecentInteraction(threshold: number): boolean {
return getTimeSinceLastInteraction() < threshold
}
function shouldNotify(threshold: number): boolean {
return process.env.NODE_ENV !== 'test' && !hasRecentInteraction(threshold)
}
// NOTE: User interaction tracking is now done in App.tsx's processKeysInBatch
// function, which calls updateLastInteractionTime() when any input is received.
// This avoids having a separate stdin 'data' listener that would compete with
// the main 'readable' listener and cause dropped input characters.
/**
* Hook that manages desktop notifications after a timeout period.
*
* Shows a notification in two cases:
* 1. Immediately if the app has been idle for longer than the threshold
* 2. After the specified timeout if the user doesn't interact within that time
*
* @param message - The notification message to display
* @param timeout - The timeout in milliseconds (defaults to 6000ms)
*/
export function useNotifyAfterTimeout(
message: string,
notificationType: string,
): void {
const terminal = useTerminalNotification()
// Reset interaction time when hook is called to make sure that requests
// that took a long time to complete don't pop up a notification right away.
// Must be immediate because useEffect runs after Ink's render cycle has
// already flushed; without it the timestamp stays stale and a premature
// notification fires if the user is idle (no subsequent renders to flush).
useEffect(() => {
updateLastInteractionTime(true)
}, [])
useEffect(() => {
let hasNotified = false
const timer = setInterval(() => {
if (shouldNotify(DEFAULT_INTERACTION_THRESHOLD_MS) && !hasNotified) {
hasNotified = true
clearInterval(timer)
void sendNotification({ message, notificationType }, terminal)
}
}, DEFAULT_INTERACTION_THRESHOLD_MS)
return () => clearInterval(timer)
}, [message, notificationType, terminal])
}