forked from sheepzh/time-tracker-4-browser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwindow.ts
More file actions
93 lines (83 loc) · 2.89 KB
/
window.ts
File metadata and controls
93 lines (83 loc) · 2.89 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
import { IS_ANDROID, IS_FIREFOX } from "@util/constant/environment"
import { handleError } from "./common"
export function listAllWindows(): Promise<chrome.windows.Window[]> {
if (IS_ANDROID) {
// windows API not supported on Firefox for Android
return Promise.resolve([])
}
return new Promise(resolve => chrome.windows.getAll(windows => {
handleError("listAllWindows")
resolve(windows || [])
}))
}
export function isNoneWindowId(windowId: number) {
if (IS_ANDROID) {
return false
}
return !windowId || windowId === chrome.windows.WINDOW_ID_NONE
}
/**
* Reduce invoking to improve memory leak of Firefox
*
* @see https://github.com/sheepzh/time-tracker-4-browser/issues/599
*/
class FocusedWindowCtx {
last?: number | undefined
listened: boolean = false
windowsTypes: `${chrome.windows.WindowType}`[]
constructor(windowTypes: `${chrome.windows.WindowType}`[]) {
this.windowsTypes = windowTypes
}
async apply(): Promise<number | undefined> {
if (IS_ANDROID) {
return undefined
}
if (this.last) {
return isNoneWindowId(this.last) ? undefined : this.last
}
// init
this.last = await this.getInner()
if (!this.listened) {
// filter argument is not supported for Firefox
// @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/onFocusChanged#addlistener_syntax
IS_FIREFOX
? chrome.windows.onFocusChanged.addListener(wid => this.last = wid)
: chrome.windows.onFocusChanged.addListener(wid => this.last = wid, { windowTypes: this.windowsTypes })
this.listened = true
}
return this.last
}
private getInner(): Promise<number | undefined> {
return new Promise(resolve => chrome.windows.getLastFocused(
// Only find normal window
{ windowTypes: ['normal'] },
window => {
handleError('getFocusedNormalWindow')
const { focused, id } = window
if (!focused || !id || isNoneWindowId(id)) {
resolve(undefined)
} else {
resolve(id)
}
}
))
}
}
const context = new FocusedWindowCtx(['normal'])
export const getFocusedNormalWindowId = () => context.apply()
export async function getWindow(id: number): Promise<chrome.windows.Window | undefined> {
if (IS_ANDROID) {
return
}
return new Promise(resolve => chrome.windows.get(id, win => resolve(win)))
}
type _Handler = (windowId: number) => void
export function onNormalWindowFocusChanged(handler: _Handler) {
if (IS_ANDROID) {
return
}
chrome.windows.onFocusChanged.addListener(windowId => {
handleError('onWindowFocusChanged')
handler(windowId)
})
}