forked from LiveTL/HyperChat
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchat-background.ts
More file actions
94 lines (82 loc) · 3.04 KB
/
chat-background.ts
File metadata and controls
94 lines (82 loc) · 3.04 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 { isLiveTL } from '../ts/chat-constants';
const noUpdateKeys = new Set(['hc.bytes.used', 'hc.bytes.update']);
const oneDay = 1000 * 60 * 60 * 24;
const storageget = (key: string): any => chrome.storage.local.get(key).then(r => r[key]);
const defaultTo0 = (value: any): number => Number.isNaN(value) ? 0 : value;
chrome.action.onClicked.addListener(() => {
if (isLiveTL) {
chrome.tabs.create({ url: 'https://livetl.app' }, () => {});
} else {
chrome.tabs.create({ url: 'https://livetl.app/hyperchat' }, () => {});
}
});
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'getFrameInfo') {
sendResponse({ tabId: sender.tab?.id, frameId: sender.frameId });
} else if (request.type === 'createPopup') {
chrome.windows.create({
url: request.url,
type: 'popup'
}, () => {});
}
});
chrome.runtime.onConnect.addListener(hc => {
const { frameId, tabId } = JSON.parse(hc.name) as { frameId: number, tabId: number };
const interceptorPort = chrome.tabs.connect(tabId, { frameId });
const onInterceptorMessage = (msg: any): void => {
hc.postMessage(msg);
};
interceptorPort.onMessage.addListener(onInterceptorMessage);
interceptorPort.onDisconnect.addListener(() => {
interceptorPort.onMessage.removeListener(onInterceptorMessage);
hc.disconnect();
});
const onHcMessage = (msg: any): void => {
interceptorPort.postMessage(msg);
};
hc.onMessage.addListener(onHcMessage);
hc.onDisconnect.addListener(() => {
hc.onMessage.removeListener(onHcMessage);
interceptorPort.disconnect();
});
});
// see https://i.imgur.com/cGciqrX.png
chrome.storage.onChanged.addListener((changes, areaName) => {
if (areaName !== 'local') return;
let delta = 0;
for (const key of Object.keys(changes)) {
if (noUpdateKeys.has(key)) continue;
const { oldValue, newValue } = changes[key];
delta += oldValue === undefined
? (key + JSON.stringify(newValue)).length
: JSON.stringify(newValue).length - JSON.stringify(oldValue).length;
}
if (delta === 0) return;
// avoid top-level async
// see https://stackoverflow.com/a/53024910
(async () => {
const toWrite: Record<string, any> = {};
const data = await Promise.all([
storageget('hc.bytes.used'),
storageget('hc.bytes.lastupdate')
]);
let bytesused = defaultTo0(data[0]);
const lastupdate = defaultTo0(data[1]);
const now = Date.now();
// see https://i.imgur.com/S0i9oS4.png
// https://i.imgur.com/PpBepQ0.png
if (now - lastupdate >= oneDay) {
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1385832#c20
bytesused = new TextEncoder().encode(
Object.entries(await chrome.storage.local.get())
.map(([key, value]) => key + JSON.stringify(value))
.join('')
).length;
toWrite['hc.bytes.lastupdate'] = now;
}
// storage transaction with 2 awaits -> potential data race???
toWrite['hc.bytes.used'] = bytesused + delta;
await chrome.storage.local.set(toWrite);
})();
return true;
});