微信阅读禅模式

按四次a/点击Zen按钮,开启/关闭禅模式

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         WeRead Zen Mode
// @name:zh-CN   微信阅读禅模式
// @description:zh-CN  按四次a/点击Zen按钮,开启/关闭禅模式
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Toggle zen mode on WeRead by pressing 'a' three times
// @author       Van
// @match        https://weread.qq.com/web/reader/*
// @grant        none
// @license      MIT 
// ==/UserScript==

(function () {
  'use strict';

  // 计数器和状态
  let zCount = 0;
  let zenModeActive = false;
  let originalDisplayStates = {}; // 存储原始display状态

  // 查找目标元素
  function findTargetElement() {
    return document.querySelector('.reader_float_review_with_range_panel_wrapper');
  }

  // 隐藏指定的元素 - 带淡出效果
  function hideSpecificElements() {
    // 要隐藏的元素选择器
    const elementsToHide = [
      '.readerTopBar',
      '.readerControls.readerControls' // 注意:这个选择器可能需要根据实际HTML结构调整
    ];

    elementsToHide.forEach(selector => {
      const elements = document.querySelectorAll(selector);
      elements.forEach(element => {
        // 保存原始display和opacity状态
        originalDisplayStates[element] = {
          display: element.style.display,
          opacity: element.style.opacity,
          transition: element.style.transition
        };

        // 设置淡出过渡
        element.style.transition = 'opacity 0.3s ease-in-out';
        element.style.opacity = '0';

        // 在过渡结束后隐藏元素
        setTimeout(() => {
          element.style.display = 'none';
        }, 300);
      });
    });
  }

  // 显示指定的元素 - 带淡入效果
  function showSpecificElements() {
    // 要显示的元素选择器
    const elementsToShow = [
      '.readerTopBar',
      '.readerControls.readerControls'
    ];

    elementsToShow.forEach(selector => {
      const elements = document.querySelectorAll(selector);
      elements.forEach(element => {
        if (originalDisplayStates.hasOwnProperty(element)) {
          // 设置为可见但透明
          element.style.display = originalDisplayStates[element].display || '';
          element.style.opacity = '0';
          element.style.transition = 'opacity 0.3s ease-in-out';

          // 触发重排后设置不透明度
          element.offsetHeight; // force reflow
          element.style.opacity = '1';

          // 恢复原始过渡设置
          setTimeout(() => {
            element.style.transition = originalDisplayStates[element].transition || '';
          }, 300);
        }
      });
    });

    // 清空存储的状态
    originalDisplayStates = {};
  }

  // 切换zen模式
  function toggleZenMode() {
    if (zenModeActive) {
      // 退出zen模式
      showSpecificElements();
      zenModeActive = false;
      showNotification('退出 Zen 模式');
      // 更新按钮状态
      updateZenButton();
    } else {
      // 进入zen模式
      hideSpecificElements();
      zenModeActive = true;
      showNotification('进入 Zen 模式');
      // 更新按钮状态
      updateZenButton();
    }
  }

  // 显示通知弹窗
  function showNotification(message) {
    // 检查是否已存在通知
    const existingNotification = document.getElementById('wz-zen-notification');
    if (existingNotification) {
      // 如果存在,移除旧的
      existingNotification.remove();
    }

    const notification = document.createElement('div');
    notification.id = 'wz-zen-notification';
    notification.textContent = message;
    notification.style.cssText = `
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background-color: rgba(0, 0, 0, 0.8);
                color: white;
                padding: 15px 30px;
                border-radius: 8px;
                font-size: 18px;
                z-index: 10000;
                opacity: 0;
                transition: opacity 0.3s ease-in-out;
            `;

    document.body.appendChild(notification);

    // 触发动画
    setTimeout(() => {
      notification.style.opacity = '1';
    }, 10);

    // 2秒后开始淡出
    setTimeout(() => {
      notification.style.opacity = '0';
      // 0.3秒后完全移除
      setTimeout(() => {
        if (notification.parentNode) {
          notification.parentNode.removeChild(notification);
        }
      }, 300);
    }, 2000); // 2秒显示时间
  }

  // 创建zen模式切换按钮
  function createZenButton() {
    const button = document.createElement('div');
    button.id = 'wz-zen-toggle-button';
    button.innerHTML = ' Zen ';
    button.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            width: 60px;
            height: 30px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 15px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 9999;
            opacity: 0.9;
            transition: all 0.3s ease;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3);
        `;

    // 添加悬停效果
    button.addEventListener('mouseenter', function () {
      this.style.opacity = '1';
      this.style.transform = 'scale(1.05)';
      resetButtonAutoHideTimer(); // 重置自动隐藏计时器
    });

    button.addEventListener('mouseleave', function () {
      this.style.opacity = '0.9';
      this.style.transform = 'scale(1)';
    });

    // 点击事件
    button.addEventListener('click', function () {
      toggleZenMode();
      resetButtonAutoHideTimer(); // 重置自动隐藏计时器
    });

    document.body.appendChild(button);
    updateZenButton(); // 初始化按钮状态

    // 设置自动隐藏计时器
    startButtonAutoHideTimer();
  }

  // 更新按钮状态
  function updateZenButton() {
    const button = document.getElementById('wz-zen-toggle-button');
    if (!button) return;

    if (zenModeActive) {
      button.style.backgroundColor = '#28a745'; // 绿色表示激活状态
      button.textContent = ' Zen ';
      button.title = '点击退出 Zen 模式';
    } else {
      button.style.backgroundColor = '#007bff'; // 蓝色表示非激活状态
      button.textContent = ' Zen ';
      button.title = '点击进入 Zen 模式';
    }
  }

  // 等待DOM加载完成并持续检查目标元素
  function waitForTargetElementAndSetup() {
    const targetElement = findTargetElement();
    if (targetElement) {
      setupKeyboardListener();
      // 创建浮动按钮
      if (!document.getElementById('wz-zen-toggle-button')) {
        createZenButton();
      }
      console.log('WeRead Zen Mode: Target element found, keyboard listener set up');
    } else {
      // 如果没找到元素,继续等待
      setTimeout(waitForTargetElementAndSetup, 1000);
    }
  }

  // 设置键盘监听器
  function setupKeyboardListener() {
    // 防止重复添加事件监听器
    if (window.wereadZenModeListenerAdded) {
      return;
    }

    window.wereadZenModeListenerAdded = true;

    // 键盘事件监听 - 使用更全局的事件监听
    document.addEventListener('keydown', function (event) {
      // 检查是否在输入框中,避免在文本输入时触发
      const activeElement = document.activeElement;
      if (activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA')) {
        return;
      }

      if (event.key === 'a' || event.key === 'A') {
        // 阻止默认行为以避免与其他功能冲突
        event.preventDefault();
        zCount++;
        if (zCount === 3) {
          toggleZenMode();
          zCount = 0; // 重置计数器
        }
      } else {
        zCount = 0; // 重置计数器
      }
    }, true); // 使用捕获阶段以确保事件被捕捉
  }

  // 页面加载完成后开始等待目标元素
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () {
      console.log('WeRead Zen Mode: DOM loaded, waiting for target element...');
      waitForTargetElementAndSetup();
    });
  } else {
    console.log('WeRead Zen Mode: Document already loaded, waiting for target element...');
    waitForTargetElementAndSetup();
  }

  // 同时在页面完全加载后也检查
  window.addEventListener('load', function () {
    console.log('WeRead Zen Mode: Window loaded, waiting for target element...');
    waitForTargetElementAndSetup();
  });

  // 自动隐藏计时器变量
  let buttonAutoHideTimer = null;

  // 开始自动隐藏计时器
  function startButtonAutoHideTimer() {
    if (buttonAutoHideTimer) {
      clearTimeout(buttonAutoHideTimer);
    }

    buttonAutoHideTimer = setTimeout(() => {
      hideButtonToEdge();
    }, 3000); // 3秒无操作后自动缩进到边缘
  }

  // 重置自动隐藏计时器
  function resetButtonAutoHideTimer() {
    if (buttonAutoHideTimer) {
      clearTimeout(buttonAutoHideTimer);
    }

    // 恢复按钮到正常位置
    const button = document.getElementById('wz-zen-toggle-button');
    if (button) {
      button.style.right = '20px';
      button.style.transform = 'translateX(0)';
    }

    // 重新开始计时器
    buttonAutoHideTimer = setTimeout(() => {
      hideButtonToEdge();
    }, 3000);
  }

  // 隐藏按钮到边缘
  function hideButtonToEdge() {
    const button = document.getElementById('wz-zen-toggle-button');
    if (button) {
      // 移动到右侧边缘,只显示一半
      button.style.right = '-20px'; // 负值使按钮部分隐藏在右侧边缘
      button.style.transform = 'translateX(0)';
    }
  }

  // 为页面添加全局鼠标移动监听,重置计时器
  function setupGlobalActivityListener() {
    document.addEventListener('mousemove', resetButtonAutoHideTimer);
    document.addEventListener('keydown', resetButtonAutoHideTimer);
    document.addEventListener('click', resetButtonAutoHideTimer);
  }

  // 在适当位置调用全局监听器设置
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', setupGlobalActivityListener);
  } else {
    setupGlobalActivityListener();
  }

})();