38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
import { useCallback, useSyncExternalStore } from 'react'
|
|
import { formatDuration } from '../utils/format.js'
|
|
|
|
/**
|
|
* Hook that returns formatted elapsed time since startTime.
|
|
* Uses useSyncExternalStore with interval-based updates for efficiency.
|
|
*
|
|
* @param startTime - Unix timestamp in ms
|
|
* @param isRunning - Whether to actively update the timer
|
|
* @param ms - How often should we trigger updates?
|
|
* @param pausedMs - Total paused duration to subtract
|
|
* @param endTime - If set, freezes the duration at this timestamp (for
|
|
* terminal tasks). Without this, viewing a 2-min task 30 min after
|
|
* completion would show "32m".
|
|
* @returns Formatted duration string (e.g., "1m 23s")
|
|
*/
|
|
export function useElapsedTime(
|
|
startTime: number,
|
|
isRunning: boolean,
|
|
ms: number = 1000,
|
|
pausedMs: number = 0,
|
|
endTime?: number,
|
|
): string {
|
|
const get = () =>
|
|
formatDuration(Math.max(0, (endTime ?? Date.now()) - startTime - pausedMs))
|
|
|
|
const subscribe = useCallback(
|
|
(notify: () => void) => {
|
|
if (!isRunning) return () => {}
|
|
const interval = setInterval(notify, ms)
|
|
return () => clearInterval(interval)
|
|
},
|
|
[isRunning, ms],
|
|
)
|
|
|
|
return useSyncExternalStore(subscribe, get, get)
|
|
}
|