Download vetcopilot-app/src/hooks/useIdleTimer.ts from WWsCa/VetNet-LCPS: direct link, hf CLI and curl.
- Browser
- Download file 2.59 kB
-
https://huggingface.co/WWsCa/VetNet-LCPS/resolve/main/vetcopilot-app/src/hooks/useIdleTimer.ts
- Command line
-
hf download hf://WWsCa/VetNet-LCPS/vetcopilot-app/src/hooks/useIdleTimer.ts
-
curl -L -o useIdleTimer.ts https://huggingface.co/WWsCa/VetNet-LCPS/resolve/main/vetcopilot-app/src/hooks/useIdleTimer.ts
2.59 kB
| /** | |
| * useIdleTimer Hook | |
| * | |
| * 检测用户空闲状态(默认 5 分钟无操作)。 | |
| * 监听鼠标移动、键盘按下、触摸等事件,空闲时触发 onIdle 回调。 | |
| * | |
| * 用法: | |
| * const { isIdle, resetTimer } = useIdleTimer({ | |
| * timeout: 5 * 60 * 1000, // 5 分钟 | |
| * onIdle: () => console.log('用户空闲'), | |
| * onActive: () => console.log('用户恢复活动'), | |
| * }) | |
| */ | |
| import { useState, useEffect, useCallback, useRef } from 'react' | |
| interface UseIdleTimerOptions { | |
| /** 空闲超时时间(ms),默认 5 分钟 */ | |
| timeout?: number | |
| /** 空闲时触发 */ | |
| onIdle?: () => void | |
| /** 从空闲恢复活动时触发 */ | |
| onActive?: () => void | |
| /** 是否启用,默认 true */ | |
| enabled?: boolean | |
| } | |
| interface UseIdleTimerReturn { | |
| /** 当前是否空闲 */ | |
| isIdle: boolean | |
| /** 手动重置空闲计时器 */ | |
| resetTimer: () => void | |
| } | |
| const EVENTS = ['mousemove', 'mousedown', 'keydown', 'touchstart', 'scroll', 'wheel'] as const | |
| export function useIdleTimer(options: UseIdleTimerOptions = {}): UseIdleTimerReturn { | |
| const { timeout = 5 * 60 * 1000, onIdle, onActive, enabled = true } = options | |
| const [isIdle, setIsIdle] = useState(false) | |
| const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null) | |
| const isIdleRef = useRef(false) | |
| const onIdleRef = useRef(onIdle) | |
| const onActiveRef = useRef(onActive) | |
| onIdleRef.current = onIdle | |
| onActiveRef.current = onActive | |
| const clearTimer = useCallback(() => { | |
| if (timerRef.current) { | |
| clearTimeout(timerRef.current) | |
| timerRef.current = null | |
| } | |
| }, []) | |
| const startTimer = useCallback(() => { | |
| clearTimer() | |
| if (!enabled) return | |
| timerRef.current = setTimeout(() => { | |
| isIdleRef.current = true | |
| setIsIdle(true) | |
| onIdleRef.current?.() | |
| }, timeout) | |
| }, [timeout, enabled, clearTimer]) | |
| const resetTimer = useCallback(() => { | |
| if (!enabled) return | |
| if (isIdleRef.current) { | |
| isIdleRef.current = false | |
| setIsIdle(false) | |
| onActiveRef.current?.() | |
| } | |
| startTimer() | |
| }, [enabled, startTimer]) | |
| useEffect(() => { | |
| if (!enabled) { | |
| clearTimer() | |
| return | |
| } | |
| startTimer() | |
| const handleActivity = () => { | |
| resetTimer() | |
| } | |
| EVENTS.forEach((event) => { | |
| window.addEventListener(event, handleActivity, { passive: true }) | |
| }) | |
| return () => { | |
| clearTimer() | |
| EVENTS.forEach((event) => { | |
| window.removeEventListener(event, handleActivity) | |
| }) | |
| } | |
| }, [enabled, startTimer, resetTimer, clearTimer]) | |
| return { isIdle, resetTimer } | |
| } | |