您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Rearranges "Playback Speed" and "Quality" settings in YouTube video settings for improved accessibility.
// ==UserScript== // @name YouTube Settings Rearranger // @namespace http://tampermonkey.net/ // @version 1.0 // @description Rearranges "Playback Speed" and "Quality" settings in YouTube video settings for improved accessibility. // @author malordin // @match https://www.youtube.com/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Debug mode flag const DEBUG = true; /** * Logs messages to the console with a custom tag. * @param {string} message - The message to log. * @param {string} type - The type of log ('log', 'warn', 'error'). */ function log(message, type = 'log') { if (!DEBUG) return; const LOG_TAG = '[YouTubeSettingsRearranger]'; switch(type) { case 'log': console.log(`${LOG_TAG} ${message}`); break; case 'warn': console.warn(`${LOG_TAG} ${message}`); break; case 'error': console.error(`${LOG_TAG} ${message}`); break; default: console.log(`${LOG_TAG} ${message}`); } } // Flag to track if rearrangement has been done for the current menu open let rearranged = false; // SVG path prefixes for identifying menu items const PLAYBACK_SPEED_SVG_PREFIX = "M10,8v8l6-4L10,8L10,8z"; const QUALITY_SVG_PREFIX = "M15,17h6v1h-6V17z"; /** * Identifies the "Playback Speed" and "Quality" menu items based on their SVG icons. * @returns {Object} An object containing the playbackSpeedItem and qualityItem elements. */ function identifyMenuItems() { const menuItems = document.querySelectorAll('.ytp-panel-menu .ytp-menuitem'); log(`Found ${menuItems.length} menu items`); let playbackSpeedItem = null; let qualityItem = null; menuItems.forEach((item, index) => { const svgPath = item.querySelector('.ytp-menuitem-icon svg path'); if (svgPath) { const dAttribute = svgPath.getAttribute('d'); if (dAttribute.startsWith(PLAYBACK_SPEED_SVG_PREFIX)) { playbackSpeedItem = item; log('Found "Playback Speed"'); } if (dAttribute.startsWith(QUALITY_SVG_PREFIX)) { qualityItem = item; log('Found "Quality"'); } } else { log(`Item ${index + 1} does not contain an SVG path`, 'warn'); } }); return { playbackSpeedItem, qualityItem, menuItems }; } /** * Rearranges the "Playback Speed" menu item to be immediately before the "Quality" menu item. */ function rearrangeSettingsMenu() { log('Initializing menu rearrangement'); const { playbackSpeedItem, qualityItem, menuItems } = identifyMenuItems(); // Check if both items are found if (playbackSpeedItem && qualityItem) { // Check if "Playback Speed" is already immediately before "Quality" const nextSibling = playbackSpeedItem.nextElementSibling; if (nextSibling === qualityItem) { log('Rearrangement not needed, items are already in the correct order'); return; } try { // Move "Playback Speed" before "Quality" qualityItem.parentNode.insertBefore(playbackSpeedItem, qualityItem); log('Rearrangement successful'); rearranged = true; // Set the flag to prevent repeated rearrangement } catch (error) { log(`Error during rearrangement: ${error}`, 'error'); } } else { if (!playbackSpeedItem) { log('"Playback Speed" not found', 'warn'); } if (!qualityItem) { log('"Quality" not found', 'warn'); } } } // MutationObserver to watch for changes in the DOM const observer = new MutationObserver((mutations, obs) => { // Check if the settings menu is visible const settingsMenu = document.querySelector('.ytp-panel-menu'); const isMenuVisible = settingsMenu && settingsMenu.offsetParent !== null; if (isMenuVisible && !rearranged) { log('Settings menu opened'); // Add a slight delay to ensure the menu is fully loaded setTimeout(() => { rearrangeSettingsMenu(); }, 200); // Delay in milliseconds } if (!isMenuVisible && rearranged) { log('Settings menu closed'); rearranged = false; // Reset the flag when the menu is closed } }); // Start observing the document body for changes observer.observe(document.body, { childList: true, subtree: true }); log('Script activated and observing DOM changes'); })();