Skip to content

Instantly share code, notes, and snippets.

@mohno007
Last active August 6, 2021 18:02
Show Gist options
  • Save mohno007/49611fbf8f4675562e53cda2783cb0fa to your computer and use it in GitHub Desktop.
Save mohno007/49611fbf8f4675562e53cda2783cb0fa to your computer and use it in GitHub Desktop.
Add volume and mute controls for Google Meet
// ==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 });
})();
@DevWannabe-dot
Copy link

Great shit bro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment