Forked from mohno007/google_meet_audio_control.user.js
Created
August 6, 2021 17:59
-
-
Save DevWannabe-dot/296195c9e5b0b3d9a30e40f8861eacf7 to your computer and use it in GitHub Desktop.
Add volume and mute controls for Google Meet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Google Meet Audio Control | |
// @namespace http://tampermonkey.net/ | |
// @version 0.2.0 | |
// @description Add volume and mute controls for Google Meet | |
// @author mohno007 | |
// @license CC0-1.0 | |
// @downloadURL https://gist.github.com/mohno007/49611fbf8f4675562e53cda2783cb0fa/raw/google_meet_audio_control.user.js | |
// @updateURL https://gist.github.com/mohno007/49611fbf8f4675562e53cda2783cb0fa/raw/google_meet_audio_control.user.js | |
// @match https://meet.google.com/* | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
const mount = ({ root, view, reducers, initialState }) => { | |
const reduce = (state) => { | |
const mountedReducers = reducers(state); | |
const actions = new Proxy({}, { | |
get: (target, prop, receiver) => (...args) => { | |
const newState = mountedReducers[prop](...args); | |
reduce(newState); | |
}, | |
}) | |
const newView = view({ state, actions }); | |
[...root.childNodes].forEach((node) => node.remove()); | |
root.appendChild(newView); | |
}; | |
reduce(initialState); | |
}; | |
const addChild = (parent, child) => { | |
if (child == null) {} | |
else if (child instanceof Array) { child.forEach((c) => addChild(parent, c)); } | |
else if (child instanceof HTMLElement || child instanceof DocumentFragment) { parent.appendChild(child); } | |
else { parent.appendChild(document.createTextNode(child)); } | |
}; | |
const h = (name, props = {}, children = []) => { | |
const elem = name && name.length > 0 ? document.createElement(name) : document.createDocumentFragment(); | |
for (const [prop, value] of Object.entries(props)) { | |
if (prop === 'class') { | |
elem.className = value; | |
} else if (prop.startsWith('on') && typeof value === 'function') { | |
const eventName = prop.slice(2).toLowerCase(); | |
elem.addEventListener(eventName, value); | |
} else if (prop === 'style' && typeof value === 'object') { | |
Object.assign(elem.style, value); | |
} else { | |
elem[prop] = value; | |
} | |
} | |
for (const child of children) { | |
addChild(elem, child); | |
} | |
return elem; | |
}; | |
const audioView = ({ audio, onChange }) => { | |
const handleVolumeChange = (ev) => { | |
const value = ev.target.value; | |
onChange({ type: 'volume', value }); | |
}; | |
const handleToggleMute = (ev) => { | |
ev.preventDefault(); | |
onChange({ type: 'mute', value: !audio.muted }); | |
}; | |
return h('div', {}, [ | |
h('input', { type: 'range', min: 0, max: 100, style: { width: '180px' }, onChange: handleVolumeChange, value: audio.volume }), | |
h('button', { type: 'button', style: { width: '40px', background: audio.muted ? '#F99' : '#eee' }, onClick: handleToggleMute }, [audio.muted ? '🔇' : '🔊']), | |
]); | |
}; | |
const view = ({ state, actions }) => { | |
const handleAudioChange = (audio) => (ev) => { | |
if (ev.type === 'volume') { | |
actions.updateVolume({ audio, value: ev.value }); | |
} else if (ev.type === 'mute') { | |
actions.updateMuted({ audio, value: ev.value }); | |
} | |
}; | |
return h('div', { | |
style: { | |
zIndex: 2**31-1, | |
position: 'fixed', | |
top: 0, | |
left: 'calc(50vw - 120px)', | |
width: '240px', | |
margin: 0, | |
padding: 0, | |
opacity: 0.2, | |
transition: 'opacity .1s ease-in-out', | |
}, | |
onMouseEnter: (ev) => { ev.target.style.opacity = 1.0; }, | |
onMouseLeave: (ev) => { ev.target.style.opacity = 0.2; }, | |
}, [ | |
audioView({ audio: state, onChange: handleAudioChange(state) }), | |
]); | |
}; | |
const initialState = { volume: 100.0, muted: false }; | |
const reducers = (state) => ({ | |
updateVolume({ value }) { | |
[...document.querySelectorAll('audio')].forEach(e => { e.volume = value / 100.0; }); | |
console.debug(`UPDATED VOLUME ${value}`); | |
return { ...state, volume: value }; | |
}, | |
updateMuted({ value }) { | |
[...document.querySelectorAll('audio')].forEach(e => { e.muted = value; }); | |
console.debug(`UPDATED MUTED: ${value}`); | |
return { ...state, muted: value }; | |
}, | |
}); | |
const root = document.createElement('div'); | |
document.body.appendChild(root); | |
mount({ root, view, reducers, initialState }); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment