useNotifyAfterTimeout.ts
hooks/useNotifyAfterTimeout.ts
No strong subsystem tag
66
Lines
2471
Bytes
2
Exports
4
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 66 lines, 4 detected imports, and 2 detected exports.
Important relationships
Detected exports
DEFAULT_INTERACTION_THRESHOLD_MSuseNotifyAfterTimeout
Keywords
thresholdmessageuseeffecttimetimeoutnotificationupdatelastinteractiontimeuseterminalnotificationinteractiondefault_interaction_threshold_ms
Detected imports
react../bootstrap/state.js../ink/useTerminalNotification.js../services/notifier.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
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])
}