-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathidle-detector.ts
More file actions
101 lines (77 loc) · 2.77 KB
/
idle-detector.ts
File metadata and controls
101 lines (77 loc) · 2.77 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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import optionHolder from "@service/components/option-holder"
export default class IdleDetector {
fullScreen: boolean = false
autoPauseTracking: boolean = false
// By milliseconds
autoPauseInterval: number = -1
lastActiveTime: number = Date.now()
userActive: boolean = true
pauseTimeout: NodeJS.Timeout | undefined
onIdle: () => void
onActive: () => void
constructor({ onIdle, onActive }: { onIdle: () => void, onActive: () => void }) {
this.onIdle = onIdle
this.onActive = onActive
this.init()
}
needTimeout(): boolean {
return this.autoPauseTracking && this.autoPauseInterval > 0
}
isIdle() {
return this.lastActiveTime + this.autoPauseInterval <= Date.now() && !this.fullScreen
}
private async init() {
const option = await optionHolder.get()
this.processOption(option)
this.resetTimeout()
optionHolder.addChangeListener(opt => {
this.processOption(opt)
this.resetTimeout()
})
const handleActive = () => {
this.lastActiveTime = Date.now()
if (!this.needTimeout()) return
if (!this.pauseTimeout) {
// Paused, so activate
this.onActive?.()
this.resetTimeout()
}
}
window.addEventListener('mousedown', handleActive)
window.addEventListener('mousemove', handleActive)
window.addEventListener('keypress', handleActive)
window.addEventListener('scroll', handleActive)
window.addEventListener('wheel', handleActive)
document?.addEventListener('fullscreenchange', () => {
this.fullScreen = !!document?.fullscreenElement
handleActive()
})
}
private processOption(option: timer.option.StatisticsOption) {
this.autoPauseTracking = !!option?.autoPauseTracking
this.autoPauseInterval = option?.autoPauseInterval * 1000
}
private resetTimeout() {
if (!!this.pauseTimeout) {
clearTimeout(this.pauseTimeout)
this.pauseTimeout = undefined
}
if (!this.needTimeout()) return
const timeoutTs = this.lastActiveTime + this.autoPauseInterval
const now = Date.now()
const detectInterval = this.fullScreen
? this.autoPauseInterval
: timeoutTs <= now ? this.autoPauseInterval : (timeoutTs - now)
this.pauseTimeout = setTimeout(() => this.handleTimeout(), detectInterval)
}
private handleTimeout() {
this.pauseTimeout = undefined
if (!this.needTimeout()) return
if (this.isIdle()) {
// Idle interval meets
this.onIdle?.()
} else {
this.resetTimeout()
}
}
}