您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fügt einen Button für temporären Zoom hinzu für bessere Chat sichtbarkeit und Auto-Sichtbarkeit
当前为
// ==UserScript== // @name WME Quick Zoom Button // @name:en WME Quick Zoom Button // @name:es Botón de Zoom Rápido WME // @version 2025.08.03 // @description Fügt einen Button für temporären Zoom hinzu für bessere Chat sichtbarkeit und Auto-Sichtbarkeit // @description:en Adds a button for temporary zoom for better chat visibility and auto-visibility // @description:es Agrega un botón para zoom temporal para una mejor visibilidad del chat y auto-visibilidad // @author Hiwi234 // @match https://www.waze.com/editor* // @match https://www.waze.com/*/editor* // @match https://beta.waze.com/editor* // @match https://beta.waze.com/*/editor* // @grant none // @license MIT // @namespace https://gf.qytechs.cn/de/users/863740-horst-wittlich // ==/UserScript== (function() { 'use strict'; const STORAGE_KEY = { AUTO: 'wme-quick-zoom-auto', ZOOM: 'wme-quick-zoom-level', VISIBILITY: 'wme-auto-visibility' }; const translations = { 'de': { buttonText: 'Quick Zoom', buttonTooltip: 'Temporär auf Zoomstufe zoomen', sliderLabel: 'Maximale Zoomstufe:', autoLoadLabel: 'Automatisch beim Laden', visibilityLabel: 'Immer sichtbar bleiben' }, 'en': { buttonText: 'Quick Zoom', buttonTooltip: 'Temporarily zoom to level', sliderLabel: 'Maximum zoom level:', autoLoadLabel: 'Automatic on load', visibilityLabel: 'Always stay visible' }, 'es': { buttonText: 'Zoom Rápido', buttonTooltip: 'Zoom temporal al nivel', sliderLabel: 'Nivel máximo de zoom:', autoLoadLabel: 'Automático al cargar', visibilityLabel: 'Permanecer siempre visible' } }; // State management let isZooming = false; let visibilityObserver = null; let visibilityInterval = null; let focusHandler = null; function getLanguage() { const lang = navigator.language.split('-')[0]; return translations[lang] ? lang : 'en'; } function getAutoZoomSetting() { try { return localStorage.getItem(STORAGE_KEY.AUTO) === 'true'; } catch (e) { console.warn('[WME Quick Zoom] localStorage access failed:', e); return false; } } function setAutoZoomSetting(value) { try { localStorage.setItem(STORAGE_KEY.AUTO, String(value)); } catch (e) { console.warn('[WME Quick Zoom] localStorage write failed:', e); } } function getVisibilitySetting() { try { return localStorage.getItem(STORAGE_KEY.VISIBILITY) === 'true'; } catch (e) { console.warn('[WME Quick Zoom] localStorage access failed:', e); return false; } } function setVisibilitySetting(value) { try { localStorage.setItem(STORAGE_KEY.VISIBILITY, String(value)); } catch (e) { console.warn('[WME Quick Zoom] localStorage write failed:', e); } } function getZoomLevel() { try { const stored = localStorage.getItem(STORAGE_KEY.ZOOM); return stored ? parseInt(stored) : 7; } catch (e) { console.warn('[WME Quick Zoom] localStorage access failed:', e); return 7; } } function setZoomLevel(value) { try { localStorage.setItem(STORAGE_KEY.ZOOM, String(value)); } catch (e) { console.warn('[WME Quick Zoom] localStorage write failed:', e); } } function ensureVisibility() { if (!getVisibilitySetting()) return; try { // Verschiedene Selektoren für Sichtbarkeits-Elemente const selectors = [ 'span.editor-visibility.label', '.editor-visibility', '[class*="visibility"]', '[aria-label*="visible"], [aria-label*="sichtbar"]', '[title*="visible"], [title*="sichtbar"]' ]; for (const selector of selectors) { const elements = document.querySelectorAll(selector); for (const element of elements) { const text = (element.textContent || '').toLowerCase().trim(); const ariaLabel = (element.getAttribute('aria-label') || '').toLowerCase(); const title = (element.getAttribute('title') || '').toLowerCase(); // Prüfe auf "unsichtbar" oder "invisible" if (text.includes('unsichtbar') || text.includes('invisible') || ariaLabel.includes('unsichtbar') || ariaLabel.includes('invisible') || title.includes('unsichtbar') || title.includes('invisible')) { // Suche nach klickbarem Element const clickable = element.closest('button, wz-button, [role="button"]') || element.querySelector('button, wz-button, [role="button"]') || element.parentElement?.querySelector('button, wz-button, [role="button"]'); if (clickable && typeof clickable.click === 'function') { console.log('[WME Quick Zoom] Unsichtbar erkannt, stelle auf sichtbar...'); clickable.click(); return; } } } } } catch (error) { console.warn('[WME Quick Zoom] Fehler beim Setzen der Sichtbarkeit:', error); } } function stopVisibilityMonitoring() { if (visibilityObserver) { visibilityObserver.disconnect(); visibilityObserver = null; } if (visibilityInterval) { clearInterval(visibilityInterval); visibilityInterval = null; } if (focusHandler) { window.removeEventListener('focus', focusHandler); focusHandler = null; } } function startVisibilityMonitoring() { if (!getVisibilitySetting()) return; // Stoppe vorherige Überwachung stopVisibilityMonitoring(); console.log('[WME Quick Zoom] Starte Sichtbarkeits-Überwachung...'); // MutationObserver für DOM-Änderungen visibilityObserver = new MutationObserver((mutations) => { try { let shouldCheck = false; for (const mutation of mutations) { if (mutation.type === 'childList' || mutation.type === 'attributes') { const target = mutation.target; // Prüfe relevante Bereiche if (target.classList?.contains('online-editors-list') || target.classList?.contains('editor-visibility') || target.tagName === 'WZ-BUTTON' || target.querySelector?.('.editor-visibility, wz-button')) { shouldCheck = true; break; } } } if (shouldCheck) { setTimeout(ensureVisibility, 200); } } catch (error) { console.warn('[WME Quick Zoom] Fehler in MutationObserver:', error); } }); // Beobachte relevante Container const containers = [ document.getElementById('online-editors'), document.querySelector('.map-editors'), document.body ].filter(Boolean); for (const container of containers) { try { visibilityObserver.observe(container, { childList: true, subtree: true, attributes: true, attributeFilter: ['aria-label', 'title', 'class'] }); break; // Nur ersten verfügbaren Container überwachen } catch (error) { console.warn('[WME Quick Zoom] Fehler beim Starten des Observers:', error); } } // Interval-basierte Überprüfung als Fallback visibilityInterval = setInterval(() => { try { ensureVisibility(); } catch (error) { console.warn('[WME Quick Zoom] Fehler im Visibility-Interval:', error); } }, 20000); // Alle 20 Sekunden // Focus-Event-Handler focusHandler = () => { setTimeout(() => { try { ensureVisibility(); } catch (error) { console.warn('[WME Quick Zoom] Fehler bei Focus-Überprüfung:', error); } }, 1000); }; window.addEventListener('focus', focusHandler, { passive: true }); // Erste Überprüfung setTimeout(() => { try { ensureVisibility(); } catch (error) { console.warn('[WME Quick Zoom] Fehler bei erster Überprüfung:', error); } }, 2000); } async function performQuickZoom() { if (isZooming) { console.log('[WME Quick Zoom] Zoom bereits aktiv, überspringe...'); return; } try { if (!window.W?.map?.olMap) { console.warn('[WME Quick Zoom] WME map nicht verfügbar'); return; } isZooming = true; const originalZoom = W.map.olMap.getZoom(); const targetZoom = getZoomLevel(); console.log(`[WME Quick Zoom] Zooming from ${originalZoom} to ${targetZoom}`); W.map.olMap.zoomTo(targetZoom); // Promise für verzögerte Rückkehr zum ursprünglichen Zoom return new Promise(resolve => { setTimeout(() => { try { if (window.W?.map?.olMap) { W.map.olMap.zoomTo(originalZoom); console.log(`[WME Quick Zoom] Restored zoom to ${originalZoom}`); } } catch (error) { console.error('[WME Quick Zoom] Error restoring zoom:', error); } finally { isZooming = false; resolve(); } }, 2000); }); } catch (error) { console.error('[WME Quick Zoom] Error in performQuickZoom:', error); isZooming = false; } } function createStyles() { // Prüfe ob Styles bereits existieren if (document.getElementById('wme-quick-zoom-styles')) { return; } const style = document.createElement('style'); style.id = 'wme-quick-zoom-styles'; style.textContent = ` .quick-zoom-container { display: flex; flex-direction: column; gap: 10px; padding: 10px; } .quick-zoom-slider-container { display: flex; flex-direction: column; gap: 5px; } .quick-zoom-checkbox-container { display: flex; align-items: center; gap: 5px; } .quick-zoom-label { font-size: 12px; color: inherit; } .quick-zoom-slider { width: 100%; } .quick-zoom-floating-button { position: fixed; bottom: 20px; left: 20px; z-index: 1000; background-color: #ffffff; border: 1px solid #cccccc; padding: 8px 15px; border-radius: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.2); cursor: pointer; font-weight: bold; font-family: inherit; font-size: 12px; transition: background-color 0.3s ease, box-shadow 0.3s ease; } .quick-zoom-floating-button:hover { background-color: #f0f0f0; box-shadow: 0 4px 8px rgba(0,0,0,0.3); } .quick-zoom-floating-button:active { background-color: #e0e0e0; transform: translateY(1px); } `; document.head.appendChild(style); } async function initializeQuickZoom() { try { // Warte bis WME vollständig geladen ist if (!window.W?.userscripts?.registerSidebarTab) { console.warn('[WME Quick Zoom] WME userscripts nicht verfügbar, warte...'); setTimeout(initializeQuickZoom, 1000); return; } console.log('[WME Quick Zoom] Initialisiere...'); const i18n = translations[getLanguage()]; // Erstelle CSS-Styles createStyles(); // Registriere Sidebar-Tab const { tabLabel, tabPane } = W.userscripts.registerSidebarTab("quick-zoom-script"); tabLabel.innerText = 'QZ'; tabLabel.title = i18n.buttonText; // Erstelle Container const container = document.createElement('div'); container.className = 'quick-zoom-container'; // Sidebar Button const sidebarButton = document.createElement('button'); sidebarButton.className = 'waze-btn waze-btn-small'; sidebarButton.innerText = i18n.buttonText; sidebarButton.title = `${i18n.buttonTooltip} ${getZoomLevel()}`; sidebarButton.type = 'button'; // Floating Button const floatingButton = document.createElement('button'); floatingButton.innerText = 'QZ'; floatingButton.title = `${i18n.buttonTooltip} ${getZoomLevel()}`; floatingButton.className = 'quick-zoom-floating-button'; floatingButton.type = 'button'; // Slider Container const sliderContainer = document.createElement('div'); sliderContainer.className = 'quick-zoom-slider-container'; const sliderLabel = document.createElement('label'); sliderLabel.textContent = i18n.sliderLabel; sliderLabel.className = 'quick-zoom-label'; const sliderValue = document.createElement('span'); sliderValue.className = 'quick-zoom-label'; sliderValue.textContent = getZoomLevel(); const slider = document.createElement('input'); slider.type = 'range'; slider.min = '4'; slider.max = '12'; slider.value = getZoomLevel(); slider.className = 'quick-zoom-slider'; // Event Handlers mit passiven Events const zoomHandler = (event) => { event.preventDefault(); if (!isZooming) { performQuickZoom().catch(error => { console.error('[WME Quick Zoom] Zoom-Fehler:', error); }); } }; const sliderHandler = (event) => { const value = event.target.value; sliderValue.textContent = value; setZoomLevel(value); const tooltip = `${i18n.buttonTooltip} ${value}`; sidebarButton.title = tooltip; floatingButton.title = tooltip; }; // Event Listeners hinzufügen slider.addEventListener('input', sliderHandler, { passive: true }); sidebarButton.addEventListener('click', zoomHandler); floatingButton.addEventListener('click', zoomHandler); // Auto-Zoom Checkbox const checkboxContainer = document.createElement('div'); checkboxContainer.className = 'quick-zoom-checkbox-container'; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.id = 'auto-quick-zoom-' + Date.now(); checkbox.checked = getAutoZoomSetting(); const label = document.createElement('label'); label.htmlFor = checkbox.id; label.textContent = i18n.autoLoadLabel; label.className = 'quick-zoom-label'; checkbox.addEventListener('change', (event) => { setAutoZoomSetting(event.target.checked); }, { passive: true }); // Visibility Checkbox const visibilityCheckboxContainer = document.createElement('div'); visibilityCheckboxContainer.className = 'quick-zoom-checkbox-container'; const visibilityCheckbox = document.createElement('input'); visibilityCheckbox.type = 'checkbox'; visibilityCheckbox.id = 'auto-visibility-' + Date.now(); visibilityCheckbox.checked = getVisibilitySetting(); const visibilityLabel = document.createElement('label'); visibilityLabel.htmlFor = visibilityCheckbox.id; visibilityLabel.textContent = i18n.visibilityLabel; visibilityLabel.className = 'quick-zoom-label'; visibilityCheckbox.addEventListener('change', (event) => { setVisibilitySetting(event.target.checked); if (event.target.checked) { setTimeout(startVisibilityMonitoring, 500); } else { stopVisibilityMonitoring(); } }, { passive: true }); // DOM aufbauen sliderContainer.appendChild(sliderLabel); sliderContainer.appendChild(slider); sliderContainer.appendChild(sliderValue); checkboxContainer.appendChild(checkbox); checkboxContainer.appendChild(label); visibilityCheckboxContainer.appendChild(visibilityCheckbox); visibilityCheckboxContainer.appendChild(visibilityLabel); container.appendChild(sidebarButton); container.appendChild(sliderContainer); container.appendChild(checkboxContainer); container.appendChild(visibilityCheckboxContainer); tabPane.appendChild(container); document.body.appendChild(floatingButton); // Warte bis Tab verbunden ist await W.userscripts.waitForElementConnected(tabPane); // Auto-Zoom ausführen wenn aktiviert if (getAutoZoomSetting()) { setTimeout(() => { performQuickZoom().catch(error => { console.error('[WME Quick Zoom] Auto-Zoom Fehler:', error); }); }, 2000); } // Visibility Monitoring starten wenn aktiviert if (getVisibilitySetting()) { setTimeout(startVisibilityMonitoring, 1000); } console.log('[WME Quick Zoom] Erfolgreich initialisiert'); } catch (error) { console.error('[WME Quick Zoom] Initialisierungs-Fehler:', error); } } // Cleanup beim Verlassen der Seite window.addEventListener('beforeunload', () => { stopVisibilityMonitoring(); }, { passive: true }); // Verbesserte Initialisierung function initialize() { try { if (window.W?.userscripts?.state?.isReady) { initializeQuickZoom(); } else if (window.W?.userscripts) { document.addEventListener("wme-ready", initializeQuickZoom, { once: true, passive: true }); } else { // Warte auf WME let attempts = 0; const maxAttempts = 60; // 30 Sekunden maximum const checkWME = () => { attempts++; if (window.W?.userscripts) { if (window.W.userscripts.state?.isReady) { initializeQuickZoom(); } else { document.addEventListener("wme-ready", initializeQuickZoom, { once: true, passive: true }); } } else if (attempts < maxAttempts) { setTimeout(checkWME, 500); } else { console.error('[WME Quick Zoom] WME konnte nicht geladen werden nach', maxAttempts * 500, 'ms'); } }; checkWME(); } } catch (error) { console.error('[WME Quick Zoom] Initialisierungs-Setup-Fehler:', error); } } // Start initialization if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize, { once: true, passive: true }); } else { initialize(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址