// ==UserScript== // @name LINUXDO FlowReader // @namespace linux.do_FlowReader // @match https://linux.do/t/topic/* // @icon https://linux.do/favicon.ico // @grant GM_setValue // @grant GM_getValue // @version 2.0 // @author Neuroplexus // ==/UserScript== // 注入样式 const style = document.createElement('style'); style.textContent = ` .userscript-rb .rb-overlay { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; background: rgba(0, 0, 0, 0.85) !important; display: flex !important; justify-content: center !important; align-items: center !important; z-index: 9999 !important; opacity: 0 !important; transition: opacity 0.3s ease !important; } .userscript-rb .rb-container { background: var(--secondary) !important; color: var(--primary) !important; padding: 40px !important; width: 100% !important; height: 100% !important; max-width: 100% !important; max-height: 100% !important; overflow-y: auto !important; transform: translateY(20px) !important; opacity: 0 !important; transition: all 0.3s ease !important; display: flex !important; flex-direction: column !important; } .userscript-rb .rb-overlay.show { opacity: 1 !important; } .userscript-rb .rb-overlay.show .rb-container { transform: translateY(0) !important; opacity: 1 !important; } .userscript-rb .rb-header { display: flex !important; align-items: center !important; gap: 10px !important; margin-bottom: 40px !important; } .userscript-rb .rb-icon { width: 32px !important; height: 32px !important; color: var(--tertiary) !important; } .userscript-rb .rb-title { font-size: 24px !important; font-weight: bold !important; margin: 0 !important; } .userscript-rb .rb-content { margin-bottom: 40px !important; flex: 1 !important; } .userscript-rb .rb-settings { display: grid !important; gap: 20px !important; max-width: 600px !important; margin: 0 auto !important; } .userscript-rb .rb-setting-group { display: flex !important; align-items: center !important; gap: 20px !important; } .userscript-rb .rb-setting-group label { flex: 1 !important; font-size: 16px !important; } .userscript-rb .rb-setting-group input { width: 120px !important; padding: 8px 12px !important; border: 1px solid var(--primary-low) !important; border-radius: 4px !important; background: var(--secondary) !important; color: var(--primary) !important; font-size: 14px !important; } .userscript-rb .rb-buttons { display: flex !important; justify-content: flex-end !important; gap: 10px !important; margin-top: 40px !important; } .userscript-rb .rb-btn { padding: 12px 24px !important; border: 1px solid currentColor !important; background: transparent !important; color: inherit !important; border-radius: 4px !important; cursor: pointer !important; font-size: 16px !important; transition: all 0.3s ease !important; display: flex !important; align-items: center !important; gap: 8px !important; } .userscript-rb .rb-btn:hover { background: rgba(142, 142, 160, 0.1) !important; } .userscript-rb .rb-btn svg { width: 20px !important; height: 20px !important; } .userscript-rb .rb-status { position: fixed !important; bottom: 20px !important; right: 20px !important; padding: 12px 24px !important; border-radius: 4px !important; background: var(--secondary) !important; color: var(--primary) !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important; z-index: 9998 !important; display: flex !important; align-items: center !important; gap: 8px !important; transform: translateY(100px) !important; opacity: 0 !important; transition: all 0.3s ease !important; } .userscript-rb .rb-status.show { transform: translateY(0) !important; opacity: 1 !important; } .userscript-rb .rb-status.success { border-left: 4px solid #10b981 !important; } .userscript-rb .rb-status.warning { border-left: 4px solid #f59e0b !important; } .userscript-rb .rb-status.error { border-left: 4px solid #ef4444 !important; } .userscript-rb .rb-float-button { position: fixed !important; right: 20px !important; top: 50% !important; transform: translateY(-50%) !important; background: var(--tertiary) !important; color: #fff !important; width: 48px !important; height: 48px !important; border-radius: 50% !important; display: flex !important; align-items: center !important; justify-content: center !important; cursor: pointer !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) !important; z-index: 9997 !important; transition: all 0.3s ease !important; } .userscript-rb .rb-float-button:hover { transform: translateY(-50%) scale(1.1) !important; } .userscript-rb .rb-float-button svg { width: 24px !important; height: 24px !important; } @media (prefers-color-scheme: dark) { .userscript-rb .rb-overlay { background: rgba(0, 0, 0, 0.95) !important; } .userscript-rb .rb-container, .userscript-rb .rb-status { background: var(--secondary-dark, #1a1b1e) !important; color: var(--primary-dark, #fff) !important; } .userscript-rb .rb-setting-group input { background: var(--secondary-dark, #1a1b1e) !important; border-color: var(--primary-low-dark, #2d2d2d) !important; } } @media (prefers-reduced-motion: reduce) { .userscript-rb .rb-overlay, .userscript-rb .rb-container, .userscript-rb .rb-status, .userscript-rb .rb-float-button { transition: none !important; } } `; document.head.appendChild(style); // 默认配置 const DEFAULT_CONFIG = { baseDelay: 2500, randomDelayRange: 800, minReqSize: 8, maxReqSize: 20, minReadTime: 800, maxReadTime: 3000, autoStart: false, lastPosition: 0 }; // 全局变量 let config = { ...DEFAULT_CONFIG, ...getStoredConfig() }; const topicID = window.location.pathname.split("/")[3]; const repliesInfo = document.querySelector("div[class=timeline-replies]").textContent.trim(); const [currentPosition, totalReplies] = repliesInfo.split("/").map(part => parseInt(part.trim(), 10)); const csrfToken = document.querySelector("meta[name=csrf-token]").getAttribute("content"); // 初始化 function initialize() { // 检查首次使用 if (!GM_getValue("hasAgreed", false)) { showDialog({ title: "首次使用提示", content: `
检测到这是你第一次使用LINUXDO ReadBoost,使用前你必须知晓:
使用该第三方脚本可能会导致包括并不限于账号被限制、被封禁的潜在风险,脚本不对出现的任何风险负责。
这是一个开源脚本,你可以自由审核其中的内容。
如果你同意以上内容,请点击"同意"按钮。
`, buttons: [ { text: "同意", onClick: () => { GM_setValue("hasAgreed", true); setupUI(); } }, { text: "取消", onClick: () => { showStatus("您未同意风险提示,脚本已停止运行。", "error"); throw new Error("未同意风险提示"); } } ] }); } else { setupUI(); } } // 设置UI function setupUI() { const headerButtons = document.querySelector(".header-buttons"); const settingsButton = createButton("设置", () => showSettings()); headerButtons.appendChild(settingsButton); // 添加浮动开始按钮 const floatButton = document.createElement("div"); floatButton.className = "userscript-rb"; floatButton.innerHTML = ` `; document.body.appendChild(floatButton); floatButton.querySelector(".rb-float-button").addEventListener("click", startReading); if (config.autoStart) { startReading(); } } // 创建按钮 function createButton(label, onClick) { const button = document.createElement("button"); button.className = "btn btn-small btn-icon-text"; button.innerHTML = ` `; button.addEventListener("click", onClick); return button; } // 显示对话框 function showDialog({ title, content, buttons = [] }) { const wrapper = document.createElement("div"); wrapper.className = "userscript-rb"; const overlay = document.createElement("div"); overlay.className = "rb-overlay"; overlay.innerHTML = `