WeRead Zen Mode

Toggle zen mode on WeRead by pressing 'a' three times

// ==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();
  }

})();