fix(label): inactivityTimer
This commit is contained in:
@@ -49,11 +49,7 @@ import { useDescToolsStore } from "./useDescToolsStore"
|
|||||||
import { useKeyboardStore } from "./useKeyBoardStore"
|
import { useKeyboardStore } from "./useKeyBoardStore"
|
||||||
import { usePaperStore } from "./usePaperStore"
|
import { usePaperStore } from "./usePaperStore"
|
||||||
import { useRightToolsStore } from "./useRightToolsStore"
|
import { useRightToolsStore } from "./useRightToolsStore"
|
||||||
import {
|
import { useIntervalStore, useLabelTimeStore } from "./useTimerStore"
|
||||||
useIntervalStore,
|
|
||||||
useLabelTimeStore,
|
|
||||||
useTimerStore,
|
|
||||||
} from "./useTimerStore"
|
|
||||||
import { useTopToolsStore } from "./useTopToolsStore"
|
import { useTopToolsStore } from "./useTopToolsStore"
|
||||||
import { findGroupKey, isEditableKeyboardTarget } from "./util"
|
import { findGroupKey, isEditableKeyboardTarget } from "./util"
|
||||||
import { safeClone } from "./utils/clone"
|
import { safeClone } from "./utils/clone"
|
||||||
@@ -89,6 +85,8 @@ const RIGHT_PANEL_SEPARATOR =
|
|||||||
const RIGHT_PANEL_SOFT_MAIN_MIN_WIDTH = 420
|
const RIGHT_PANEL_SOFT_MAIN_MIN_WIDTH = 420
|
||||||
const RIGHT_PANEL_HARD_MAIN_MIN_WIDTH = 260
|
const RIGHT_PANEL_HARD_MAIN_MIN_WIDTH = 260
|
||||||
const RIGHT_PANEL_TARGET_WIDTH = 350
|
const RIGHT_PANEL_TARGET_WIDTH = 350
|
||||||
|
const INACTIVITY_VIEW_DELAY_MS = 5 * 60 * 1000
|
||||||
|
const INACTIVITY_ACTIVITY_THROTTLE_MS = 1000
|
||||||
|
|
||||||
// utils
|
// utils
|
||||||
const getRectPoints = ([sx, sy, w, h]: number[]) => {
|
const getRectPoints = ([sx, sy, w, h]: number[]) => {
|
||||||
@@ -280,6 +278,8 @@ const LabelPage = ({
|
|||||||
const topRef = useRef<any>(null)
|
const topRef = useRef<any>(null)
|
||||||
const autoSaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
const autoSaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||||
const autoSaveInProgressRef = useRef(false)
|
const autoSaveInProgressRef = useRef(false)
|
||||||
|
const inactivityTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||||
|
const lastInactivityResetAtRef = useRef(0)
|
||||||
const paperContainerRef = useRef<any>(null)
|
const paperContainerRef = useRef<any>(null)
|
||||||
const qaToolContainerRef = useRef<any>(null)
|
const qaToolContainerRef = useRef<any>(null)
|
||||||
const [isConfirmSave, setIsConfirmSave] = useState(false)
|
const [isConfirmSave, setIsConfirmSave] = useState(false)
|
||||||
@@ -2472,22 +2472,86 @@ const LabelPage = ({
|
|||||||
}
|
}
|
||||||
}, [updateSplitterSizes])
|
}, [updateSplitterSizes])
|
||||||
|
|
||||||
|
const clearInactivityTimer = useCallback(() => {
|
||||||
|
if (inactivityTimerRef.current !== null) {
|
||||||
|
clearTimeout(inactivityTimerRef.current)
|
||||||
|
inactivityTimerRef.current = null
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const scheduleInactivityViewMode = useCallback(() => {
|
||||||
|
clearInactivityTimer()
|
||||||
|
inactivityTimerRef.current = setTimeout(() => {
|
||||||
|
const topToolsState = useTopToolsStore.getState()
|
||||||
|
if (!topToolsState.isView) {
|
||||||
|
topToolsState.setIsView(true)
|
||||||
|
}
|
||||||
|
}, INACTIVITY_VIEW_DELAY_MS)
|
||||||
|
}, [clearInactivityTimer])
|
||||||
|
|
||||||
|
const reportUserActivity = useCallback(
|
||||||
|
(force = false) => {
|
||||||
|
if (useTopToolsStore.getState().isView) return
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
if (
|
||||||
|
!force &&
|
||||||
|
now - lastInactivityResetAtRef.current < INACTIVITY_ACTIVITY_THROTTLE_MS
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lastInactivityResetAtRef.current = now
|
||||||
|
scheduleInactivityViewMode()
|
||||||
|
},
|
||||||
|
[scheduleInactivityViewMode]
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isView) {
|
if (isView) {
|
||||||
const delay = 5 * 60000
|
lastInactivityResetAtRef.current = 0
|
||||||
// 编辑模式下,修改labelData时启动或更新定时器
|
clearInactivityTimer()
|
||||||
useTimerStore.getState().startTimer(() => {
|
return
|
||||||
useTopToolsStore.getState().setIsView(true)
|
|
||||||
}, delay)
|
|
||||||
} else {
|
|
||||||
useTimerStore.getState().clearTimer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组件卸载时清理定时器
|
// 使用真实输入事件追踪活跃度,避免进行中的标注因 labelData 未变化被误判为空闲。
|
||||||
return () => {
|
reportUserActivity(true)
|
||||||
useTimerStore.getState().clearTimer()
|
|
||||||
|
const handlePointerDown = () => {
|
||||||
|
reportUserActivity(true)
|
||||||
}
|
}
|
||||||
}, [isView, labelData])
|
const handlePointerMove = (event: PointerEvent) => {
|
||||||
|
if (event.buttons !== 0) {
|
||||||
|
reportUserActivity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleWheel = () => {
|
||||||
|
reportUserActivity()
|
||||||
|
}
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
reportUserActivity(true)
|
||||||
|
}
|
||||||
|
const handleVisibilityChange = () => {
|
||||||
|
if (document.visibilityState === "visible") {
|
||||||
|
reportUserActivity(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("pointerdown", handlePointerDown, true)
|
||||||
|
window.addEventListener("pointermove", handlePointerMove, true)
|
||||||
|
window.addEventListener("wheel", handleWheel, true)
|
||||||
|
window.addEventListener("keydown", handleKeyDown, true)
|
||||||
|
document.addEventListener("visibilitychange", handleVisibilityChange)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("pointerdown", handlePointerDown, true)
|
||||||
|
window.removeEventListener("pointermove", handlePointerMove, true)
|
||||||
|
window.removeEventListener("wheel", handleWheel, true)
|
||||||
|
window.removeEventListener("keydown", handleKeyDown, true)
|
||||||
|
document.removeEventListener("visibilitychange", handleVisibilityChange)
|
||||||
|
clearInactivityTimer()
|
||||||
|
}
|
||||||
|
}, [clearInactivityTimer, isView, reportUserActivity])
|
||||||
|
|
||||||
// auto save
|
// auto save
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user