您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Depends on "light" theme being the default one in f-list. Adds two buttons to TamperMonkey menu itself to switch and auto-detect light/dark.
当前为
- // ==UserScript==
- // @name F-list inverted color theme with auto-detection.
- // @license MIT
- // @namespace https://www.f-list.net
- // @version 2025-02-24
- // @description Depends on "light" theme being the default one in f-list. Adds two buttons to TamperMonkey menu itself to switch and auto-detect light/dark.
- // @author Me
- // @match https://www.f-list.net/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=f-list.net
- // @require https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
- // @grant GM_registerMenuCommand
- // @grant GM_unregisterMenuCommand
- // @grant GM_addStyle
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- (function() {
- 'use strict';
- // CSS overrides. Note: the colors here are the inverse of what you want.
- const cssCustomDarkOverrides = `
- /* core changes - hue is for a more pleasant shade of background-image elements. */
- html {
- filter: invert(1) hue-rotate(180deg);
- }
- /* invert images again to return them to the original color and hue */
- .inverted-img {
- filter: invert(1) hue-rotate(180deg);
- }
- /* special cases where the core changes above don't work well */
- .messages-both .message-ad {
- background-color: #ccd !important;
- }
- .ads-text-box, .ads-text-box:focus {
- background-color: #ccd !important;
- }
- `;
- // For auto-detection.
- const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
- // Current dark mode state and mutation observer reference.
- let isDarkModeEnabled = false;
- let observer = null;
- // Saved dark mode states.
- const DarkModeStates = Object.freeze({
- AUTO: "auto",
- MANUAL_ON: "manual_on",
- MANUAL_OFF: "manual_off"
- });
- let darkModeState = GM_getValue('darkModeState', DarkModeStates.MANUAL_OFF);
- // Hold the menu command IDs so we can update their labels.
- let darkModeCommandId;
- let autoDetectCommandId;
- // Insert custom CSS overrides using jQuery.
- function enableCustomOverrides() {
- if ($('#customOverridesStyle').length === 0) {
- const $styleEl = $('<style>', { id: 'customOverridesStyle', type: 'text/css' }).text(cssCustomDarkOverrides);
- $('head').append($styleEl);
- }
- }
- // Remove custom CSS overrides.
- function disableCustomOverrides() {
- $('#customOverridesStyle').remove();
- }
- // Update GM menu commands with dynamic text based on current state.
- function updateMenuCommands() {
- if (typeof GM_unregisterMenuCommand === 'function') {
- if (darkModeCommandId) { GM_unregisterMenuCommand(darkModeCommandId); }
- if (autoDetectCommandId) { GM_unregisterMenuCommand(autoDetectCommandId); }
- }
- darkModeCommandId = GM_registerMenuCommand(
- darkModeState === DarkModeStates.MANUAL_ON ? "Disable Dark Mode" : "Enable Dark Mode",
- toggleDarkMode
- );
- autoDetectCommandId = GM_registerMenuCommand(
- darkModeState === DarkModeStates.AUTO ? "Disable Auto-Detection" : "Enable Auto-Detection",
- toggleAutoDetection
- );
- }
- // Use jQuery to add the inverted class to images, picture, and video elements.
- function addInvertedClassToNode(node) {
- const $node = $(node);
- if ($node.is('img, picture, video') && !$node.hasClass('inverted-img')) {
- $node.addClass('inverted-img');
- }
- $node.find('img, picture, video').not('.inverted-img').addClass('inverted-img');
- }
- // Enable dark mode: add custom CSS and observe the DOM for new elements.
- function enableDarkMode() {
- enableCustomOverrides();
- observer = new MutationObserver(mutations => {
- mutations.forEach(mutation => {
- mutation.addedNodes.forEach(node => {
- if (node.nodeType === Node.ELEMENT_NODE) {
- addInvertedClassToNode(node);
- }
- });
- });
- });
- observer.observe(document.body, { childList: true, subtree: true });
- $('img, picture, video').not('.inverted-img').addClass('inverted-img');
- isDarkModeEnabled = true;
- }
- // Disable dark mode: remove custom CSS and stop DOM observation.
- function disableDarkMode() {
- disableCustomOverrides();
- if (observer) {
- observer.disconnect();
- observer = null;
- }
- $('img, picture, video').removeClass('inverted-img');
- isDarkModeEnabled = false;
- }
- // Toggle dark mode manually.
- function toggleDarkMode() {
- if (isDarkModeEnabled) {
- darkModeState = DarkModeStates.MANUAL_OFF;
- disableDarkMode();
- } else {
- darkModeState = DarkModeStates.MANUAL_ON;
- enableDarkMode();
- }
- GM_setValue('darkModeState', darkModeState);
- updateMenuCommands();
- }
- // When system dark mode preference changes.
- function handleColorSchemeChange(event) {
- console.log(`Browser changed its preference. Should we use dark mode now? ${event.matches}`);
- event.matches ? enableDarkMode() : disableDarkMode();
- }
- // Update media query listener safely.
- function updateMediaQueryListener() {
- darkModeMediaQuery.removeEventListener('change', handleColorSchemeChange);
- if (darkModeState === DarkModeStates.AUTO) {
- darkModeMediaQuery.addEventListener('change', handleColorSchemeChange);
- }
- }
- // Apply auto-detection or manual override.
- function autoDetectNow() {
- updateMediaQueryListener();
- if (darkModeState === DarkModeStates.AUTO) {
- console.log(`Autodetection active; system preference is dark? ${darkModeMediaQuery.matches}`);
- darkModeMediaQuery.matches ? enableDarkMode() : disableDarkMode();
- } else {
- const manualOn = (darkModeState === DarkModeStates.MANUAL_ON);
- console.log(`Autodetection disabled. Manual override? ${manualOn}`);
- manualOn ? enableDarkMode() : disableDarkMode();
- }
- }
- // Toggle auto-detection.
- function toggleAutoDetection() {
- darkModeState = darkModeState === DarkModeStates.AUTO ? DarkModeStates.MANUAL_OFF : DarkModeStates.AUTO;
- GM_setValue('darkModeState', darkModeState);
- autoDetectNow();
- updateMenuCommands();
- }
- // Initialize.
- autoDetectNow();
- updateMenuCommands();
- })();