-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathlifecycleTracker.ts
More file actions
94 lines (84 loc) · 2.52 KB
/
Copy pathlifecycleTracker.ts
File metadata and controls
94 lines (84 loc) · 2.52 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
import type { Configuration } from '../domain/configuration'
import { dateNow } from '../tools/utils/timeUtils'
import { isWorkerEnvironment } from '../tools/globalObject'
import { addEventListener, addEventListeners, DOM_EVENT } from './addEventListener'
export type LifecycleEventName =
| 'visibilitychange'
| 'pagehide'
| 'pageshow'
| 'freeze'
| 'resume'
| 'beforeunload'
| 'prerenderingchange'
export interface LifecycleContext {
lastLifecycleEvent: LifecycleEventName | undefined
timeSinceLifecycleEvent: number | undefined
restoredFromBfcache: boolean
wasPrerendered: boolean
}
let lastEvent: { name: LifecycleEventName; at: number } | undefined
let restoredFromBfcache = false
let wasPrerendered = false
let started = false
let stopListeners: (() => void) | undefined
export function startLifecycleTracker(configuration: Configuration): void {
if (started || isWorkerEnvironment || typeof window === 'undefined') {
return
}
started = true
if (typeof document !== 'undefined' && (document as Document & { prerendering?: boolean }).prerendering) {
wasPrerendered = true
}
const { stop: stopWindowListeners } = addEventListeners(
configuration,
window,
[
DOM_EVENT.VISIBILITY_CHANGE,
DOM_EVENT.PAGE_HIDE,
DOM_EVENT.PAGE_SHOW,
DOM_EVENT.FREEZE,
DOM_EVENT.RESUME,
DOM_EVENT.BEFORE_UNLOAD,
],
(event) => {
lastEvent = { name: event.type as LifecycleEventName, at: dateNow() }
if (event.type === DOM_EVENT.PAGE_SHOW && (event as PageTransitionEvent).persisted) {
restoredFromBfcache = true
}
},
{ capture: true }
)
let stopPrerenderingListener: (() => void) | undefined
if (typeof document !== 'undefined' && 'prerendering' in document) {
stopPrerenderingListener = addEventListener(
configuration,
document,
'prerenderingchange',
() => {
wasPrerendered = true
lastEvent = { name: 'prerenderingchange', at: dateNow() }
},
{ capture: true }
).stop
}
stopListeners = () => {
stopWindowListeners()
stopPrerenderingListener?.()
}
}
export function getLifecycleContext(): LifecycleContext {
return {
lastLifecycleEvent: lastEvent?.name,
timeSinceLifecycleEvent: lastEvent ? dateNow() - lastEvent.at : undefined,
restoredFromBfcache,
wasPrerendered,
}
}
export function resetLifecycleTracker(): void {
stopListeners?.()
stopListeners = undefined
lastEvent = undefined
restoredFromBfcache = false
wasPrerendered = false
started = false
}