forked from mjmartis/discord_web_sys_ptt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.js
166 lines (141 loc) · 4.22 KB
/
content.js
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/**
* The default minimum number of ms to wait from initial shortcut message
* before ending PTT.
* @const {number}
*/
const PTT_DELAY_FIRST_DEFAULT = 100;
/**
* The number of ms to wait from last shortcut message before ending PTT.
* @const {number}
*/
const PTT_DELAY_LAST = 100;
/**
* A manually-constructed map from modifiers to their (likely) key codes. From
* https://github.com/wesbos/keycodes/blob/gh-pages/scripts.js.
* @const {!Array<!Array>}
*/
const MOD_KEY_CODES = [
['shiftKey', 16],
['ctrlKey', 17],
['altKey', 18],
['metaKey', 91],
];
/**
* The list of URL prefixes that indicate the page is an instance of the Discord
* web app.
* @const {!Array<string>}
*/
const DISCORD_APP_URLS = [
'https://discord.com/app', 'https://discord.com/channels',
];
/**
* The minimum number of ms to wait from initial shortcut message before ending
* PTT.
* @type {number}
*/
let pttDelayFirst = PTT_DELAY_FIRST_DEFAULT;
/**
* The time (in ms past the Unix epoch) at which the active PTT window should
* end, or null if there is no PTT window currently active.
* @type {?number}
*/
let pttEndTime = null;
/**
* The key code and modifier statuses with which to construct syntheic PTT key
* up/down events for this tab.
* @type {?Object<string, (number|boolean)}
*/
let keyEventInits = {bubbles: true, cancelable: true, key: "P", char: "P", shiftKey: true, ctrlKey: true, altKey: true, code: "KeyP", keyCode: 80, which: 80};
/**
* The timeout ID for the active PTT window (if one exists).
* @type {?number}
*/
let toId = null;
/**
* Whether or not this page appears to be broadcasting PTT voice. This may be a
* false positive if the page is a non-app Discord page (e.g. Discord developer
* docs).
* @type {boolean}
*/
let broadcasting = false;
/**
* Whether or not this page is a Discord web-app page. When this value is true,
* the broadcasting value should be transmitted to background script to keep the
* extension badge etc. updated.
* @type {boolean}
*/
let isDiscordApp = false;
// Listen to changes in the page's broadcasting status.
document.addEventListener('BwpttBroadcasting', function(ev) {
broadcasting = ev.detail;
if (isDiscordApp) {
browser.runtime.sendMessage({
id: 'broadcasting',
value: broadcasting,
});
}
});
/** Sends a PTT keyup event. */
function pttOff() {
pttEndTime = null;
//console.log("PTT released");
document.dispatchEvent(new KeyboardEvent('keyup', keyEventInits));
}
/**
* Extends the PTT off timeout, and sends a PTT keydown event if one hasn't
* been sent yet.
*/
function onExtShortcut() {
if (toId !== null) clearTimeout(toId);
const pttDelay = pttEndTime === null ?
pttDelayFirst :
Math.max(PTT_DELAY_LAST, pttEndTime - new Date().getTime());
toId = setTimeout(pttOff, pttDelay);
if (pttEndTime === null) {
pttEndTime = new Date().getTime() + pttDelayFirst;
//console.log("PTT pressed");
document.dispatchEvent(new KeyboardEvent('keydown', keyEventInits));
}
}
// Respond to events from the background script.
browser.runtime.onMessage.addListener(function(msg) {
if (msg.id === 'ext_shortcut_pushed') {
onExtShortcut();
}
return false;
});
// Notify background script that we're a Discord tab.
browser.runtime.sendMessage({
id: 'discord_loaded',
});
// Never broadcasting once the user navigates away.
window.addEventListener('beforeunload', function() {
broadcasting = false;
browser.runtime.sendMessage({
id: 'broadcasting',
value: broadcasting,
});
});
window.addEventListener('DOMContentLoaded', function() {
// The only comprehensive way I've found to track redirects is to watch
// mutations to the whole document body.
let observer = new MutationObserver(function(_, ob) {
isDiscordApp = DISCORD_APP_URLS.some(prefix =>
document.location.href.startsWith(prefix)
);
if (isDiscordApp) {
broadcasting = true;
browser.runtime.sendMessage({
id: 'broadcasting',
value: broadcasting,
});
// Prevent this callback from being called more than necessary (since
// body modifications are presumably frequent).
ob.disconnect();
}
});
observer.observe(document.querySelector('body'), {
childList: true,
subtree: true,
});
});