您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Кастомные иконки Google Meet: камера, микрофон, субтитры, экран, реакция, рука
// ==UserScript== // @name Google Meet — Старые иконки + Панель (сворачиваемая) // @namespace http://tampermonkey.net/ // @version 13.0 // @description Кастомные иконки Google Meet: камера, микрофон, субтитры, экран, реакция, рука // @match https://meet.google.com/* // @grant none // ==/UserScript== (function () { 'use strict'; const iconMap = { microphone: { on: 'https://i.ibb.co/0ypcDvsX/micro-23off.png', off: 'https://i.ibb.co/JWNy9rkY/micro-23on.png', }, camera: { on: 'https://i.ibb.co/XxYyJnBZ/webcam-o2ff.png', off: 'https://i.ibb.co/cXpsBL6c/webcam-2on.png', }, end: 'https://i.ibb.co/gFVNHBsc/end-the-ca23ll.png', screen: 'https://i.ibb.co/qFkpGm9s/show-scr2een.png', hand: { on: 'https://i.ibb.co/GvPhVWNR/raise-your-ha2nd.png', off: 'https://i.ibb.co/bMGwygGX/raise-your-ha2ndon.png', }, subtitles: 'https://i.ibb.co/LDk0PFhX/su2btitles.png', reaction: 'https://i.ibb.co/Hp3k5y8T/send-a-re2sponse.png', }; function getIconByLabel(label = '') { label = label.toLowerCase(); if (label.includes('micro') || label.includes('мікрофон')) { return label.includes('off') || label.includes('вимк') ? iconMap.microphone.off : iconMap.microphone.on; } if (label.includes('camera') || label.includes('камера')) { return iconMap.camera.off; } if (label.includes('leave') || label.includes('вийти')) return iconMap.end; if (label.includes('screen') || label.includes('екран') || label.includes('present')) return iconMap.screen; if (label.includes('hand') || label.includes('руку')) { return label.includes('опуст') || label.includes('вимк') ? iconMap.hand.off : iconMap.hand.on; } if (label.includes('caption') || label.includes('subtitle') || label.includes('субтитри')) return iconMap.subtitles; if (label.includes('emoji') || label.includes('реакц')) return iconMap.reaction; return null; } function getStoredIconSize() { const size = parseInt(localStorage.getItem('customIconSize'), 10); return isNaN(size) ? 28 : Math.min(Math.max(size, 16), 64); } function replaceIcon(button) { const label = button.getAttribute('aria-label') || button.getAttribute('data-tooltip') || button.title || button.innerText || ''; const iconUrl = getIconByLabel(label); if (!iconUrl) return; let existingImg = button.querySelector('.overlay-old-icon'); if (existingImg && existingImg.src === iconUrl) return; if (existingImg) existingImg.remove(); Array.from(button.querySelectorAll(':scope > svg, :scope > img')).forEach(el => { el.style.opacity = '0'; el.style.pointerEvents = 'none'; }); const img = document.createElement('img'); img.src = iconUrl; img.className = 'overlay-old-icon'; img.style.position = 'absolute'; img.style.top = '50%'; img.style.left = '50%'; img.style.transform = 'translate(-50%, -50%)'; img.style.pointerEvents = 'none'; img.style.zIndex = '10'; img.style.width = img.style.height = getStoredIconSize() + 'px'; const computedStyle = window.getComputedStyle(button); if (computedStyle.position === 'static') { button.style.position = 'relative'; } button.appendChild(img); } function scanAndReplaceButtons(root = document.body) { const buttons = []; function collectButtons(node) { if (!node || node.nodeType !== 1) return; if (node.tagName === 'BUTTON') buttons.push(node); if (node.shadowRoot) collectButtons(node.shadowRoot); node.childNodes.forEach(collectButtons); } collectButtons(root); buttons.forEach(replaceIcon); } const observer = new MutationObserver(() => { scanAndReplaceButtons(); }); observer.observe(document.body, { childList: true, subtree: true, }); scanAndReplaceButtons(); // Панель настройки const wrapper = document.createElement('div'); wrapper.style.position = 'fixed'; wrapper.style.bottom = '8px'; wrapper.style.right = '8px'; wrapper.style.zIndex = '9999'; const toggleButton = document.createElement('button'); toggleButton.textContent = '⚙️'; toggleButton.style.fontSize = '16px'; toggleButton.style.padding = '4px 8px'; toggleButton.style.cursor = 'pointer'; toggleButton.style.marginBottom = '4px'; toggleButton.style.borderRadius = '5px'; toggleButton.style.border = '1px solid #ccc'; toggleButton.style.background = '#f0f0f0'; const panel = document.createElement('div'); panel.style.background = 'white'; panel.style.border = '1px solid #ccc'; panel.style.borderRadius = '5px'; panel.style.padding = '6px'; panel.style.fontSize = '12px'; panel.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)'; const input = document.createElement('input'); input.type = 'number'; input.min = 16; input.max = 64; input.value = getStoredIconSize(); input.style.width = '60px'; input.style.marginRight = '4px'; const buttonApply = document.createElement('button'); buttonApply.textContent = 'Применить'; buttonApply.style.marginRight = '4px'; const buttonReload = document.createElement('button'); buttonReload.textContent = 'Обновить'; buttonApply.onclick = () => { localStorage.setItem('customIconSize', input.value); scanAndReplaceButtons(); }; buttonReload.onclick = () => { scanAndReplaceButtons(); }; panel.append('Размер иконок: ', input, buttonApply, buttonReload); const reactButton = document.createElement('button'); reactButton.textContent = '🎉 Реакция'; reactButton.style.marginTop = '4px'; reactButton.onclick = () => { alert('Реакция отправлена! 🎉'); }; panel.appendChild(document.createElement('br')); panel.appendChild(reactButton); toggleButton.onclick = () => { const isHidden = panel.style.display === 'none'; panel.style.display = isHidden ? 'block' : 'none'; localStorage.setItem('showIconPanel', isHidden ? '1' : '0'); }; const showPanel = localStorage.getItem('showIconPanel'); panel.style.display = showPanel === '0' ? 'none' : 'block'; wrapper.appendChild(toggleButton); wrapper.appendChild(panel); document.body.appendChild(wrapper); })();