-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontent-script.js
More file actions
92 lines (76 loc) · 3.2 KB
/
Copy pathcontent-script.js
File metadata and controls
92 lines (76 loc) · 3.2 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
const queries = {
loadingIndicator: "//div[text()='Getting ready...']",
joinBtn: "//div[@role='button'][descendant::text()='Join now'][not(@aria-disabled)]",
presentBtn: "//div[@role='button'][descendant::text()='Present']",
presentLabel: "//span[text()='Present']/text()",
micBtn: "button[aria-label*='microphone']" // DOMString
}
// Add 'Join Hybrid' button
window.onload = function () {
const loadingIndicator = getElementByXPath(queries.loadingIndicator)
if (loadingIndicator) {
const loadingObserver = new MutationObserver(function (mutationList, observer) {
// Imperfect method of determining when DOM patching is finished
const joinBtn = getElementByXPath(queries.joinBtn)
if (isVisible(joinBtn)) {
setTimeout(addJoinHybridBtn, 500) // Wait for animation to finish
observer.disconnect()
}
})
loadingObserver.observe(loadingIndicator.parentElement, { childList: true, subtree: true })
}
}
function watchAndRemoveAudioElements () {
const audioObserver = new MutationObserver(function (mutationList, observer) {
const audioEls = document.getElementsByTagName('audio')
if (audioEls.length > 0) {
Array.from(audioEls).forEach((el) => el.remove())
}
})
audioObserver.observe(document.body, { childList: true })
}
function watchAndMuteMicrophone () {
// When mic button appears (in document.body), start watching it for changes to data-is-muted attribute
const micBtnPresenceObserver = new MutationObserver(function (mutationList, observer) {
const micBtn = document.querySelector(queries.micBtn)
if (micBtn) {
if (micBtn.dataset.isMuted !== 'true') {
micBtn.click()
}
micBtnAttributeObserver.observe(micBtn, { attributes: true, attributeFilter: ['data-is-muted'] })
observer.disconnect()
}
})
micBtnPresenceObserver.observe(document.body, { subtree: true, childList: true })
// When data-is-muted attribute changes, click mic button to mute it again
const micBtnAttributeObserver = new MutationObserver(function (mutationList, observer) {
const micBtn = mutationList[0].target
if (micBtn.dataset.isMuted !== 'true') {
micBtn.click()
}
})
}
function addJoinHybridBtn () {
const joinBtn = getElementByXPath(queries.joinBtn)
const presentBtn = getElementByXPath(queries.presentBtn)
const joinBtnContainer = joinBtn.parentElement
const hybridBtn = presentBtn.cloneNode(true)
hybridBtn.removeAttribute('jsname') // leave jscontroller and jsaction to enable click animation
hybridBtn.setAttribute('id', 'join-hybrid-btn')
hybridBtn.setAttribute('data-tooltip', 'Join with audio and microphone disabled')
hybridBtn.querySelector('.google-material-icons').innerText = 'mic_off'
const label = getElementByXPath(queries.presentLabel, hybridBtn)
label.textContent = 'Join hybrid'
hybridBtn.onclick = function (event) {
watchAndRemoveAudioElements()
watchAndMuteMicrophone()
joinBtn.click()
}
joinBtnContainer.appendChild(hybridBtn)
}
function getElementByXPath(xpath, context=document) {
return document.evaluate(xpath, context, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue
}
function isVisible (el) {
return el && el.clientWidth > 0
}