微信读书笔记列表跟随当前章节滚动

笔记列表跟随当前章节滚动

当前为 2023-08-28 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         微信读书笔记列表跟随当前章节滚动
// @namespace    http://tampermonkey.net/
// @version      0.4.6
// @description  笔记列表跟随当前章节滚动
// @author       XQH
// @match        https://weread.qq.com/web/reader/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=qq.com
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';
    let noteListCssSelector = 'readerNoteList'
    let noteItemClz = 'sectionListItem_title'
    // 保存点击的上一个笔记
    let lastNote = null;
    // 笔记面板
    let notePanel = document.getElementsByClassName("readerNotePanel")[0];

    // 等待页面加载完毕
    setTimeout(function () {
        // 获取网页标题 css:.readerTopBar_title_chapter
        let title = document.querySelector(".readerTopBar_title_chapter");

        function jumpNote() {
            // 获取title文字,查找noteList中div(class:noteItemClz)子标签文字对应标签
            let titleText = title.innerText;
            let noteList = document.getElementsByClassName(noteListCssSelector)[0];
            let noteItems = noteList.getElementsByClassName(noteItemClz);
            for (let i = 0; i < noteItems.length; i++) {
                if (noteItems[i].innerText == titleText) {
                    noteList.scrollTop = noteItems[i].offsetTop - 100;
                    break;
                }
            }
            // 如果保存了上一个笔记
            if (lastNote) {
                // 滚动到笔记位置
                noteList.scrollTop = lastNote.offsetTop - 100;
            }

        }
        // 定时隐藏推广按钮
        setInterval(function () {
            // 隐藏推广按钮
            let appDownloadBtn = document.querySelector(".readerControls_item.download");
            if (appDownloadBtn) {
                appDownloadBtn.style.display = "none";
            }
            // 移动端UA下会显示打开app阅读
            let toAppBtn = document.querySelector(".readerFooter_button.blue");
            if (toAppBtn) {
                // 直接删除该元素
                toAppBtn.parentNode.removeChild(toAppBtn);
            }    
        }, 900)



        // 获取button.rbb_item
        let invoke = document.querySelector(".readerBottomBar.showShadow");



        // 为笔记列表添加点击事件



        // 为所有(sectionListItem_content noteItem_content clickable)设置点击隐藏notePanel
        let noteItems = document.getElementsByClassName("sectionListItem_content noteItem_content clickable");
        for (let i = 0; i < noteItems.length; i++) {
            noteItems[i].addEventListener("click", function () {
                // 保存到上一个笔记
                lastNote = noteItems[i];
                notePanel.style.display = "none";
                setTimeout(function () {
                    // 获取当前.app_content(div)  离顶部的距离
                    let appContent = document.querySelector(".app_content");
                    let appContentTop = Math.round(appContent.getBoundingClientRect().top);
                    // 如果top 为-75(PC) -11(MOBILE),这个高度可能受屏幕高度影响(?),需检测是否有上一页,可能需要调用翻页并重新调用跳转笔记
                    console.log("appContentTop:" + appContentTop);
                    // TODO 考虑重构代码理清逻辑
                    if (appContentTop == -75 || appContentTop == -11 || appContentTop == -12) {
                        //    则判断为上一页,调用翻页并重新调用跳转笔记
                        console.log("start to judge if it is prev page");
                        // 可以考虑每个笔记跳转时都直接切换章节再跳转避免触发翻页bug
                        setTimeout(function () {
                            // 高度无变化,判断为需要切换上一页
                            if (appContentTop == -75 || appContentTop == -11 || appContentTop == -12) {
                                // 获取 ul(clz:readerCatalog_list),
                                // 下的div(chapterItem_link chapterItem_level1)比较div中span文字
                                // 选择不与当前标题相同的item调用点击事件,再重新调用切换笔记
                                let catalogList = document.querySelector(".readerCatalog_list");
                                let catalogItems = catalogList.getElementsByClassName("chapterItem_link chapterItem_level1");
                                let titleText = title.innerText;
                                for (let i = 0; i < catalogItems.length; i++) {
                                    if (catalogItems[i].querySelector("span").innerText != titleText) {
                                        console.log("jump another chapter");
                                        catalogItems[i].dispatchEvent(
                                            new MouseEvent("click", {
                                                clientX: 1,
                                                clientY: 1,
                                            })
                                        );
                                        break;
                                    }
                                }

                                setTimeout(function () {
                                    lastNote.dispatchEvent(
                                        new MouseEvent("click", {
                                            clientX: 1,
                                            clientY: 1,
                                        })
                                    );
                                    // 跳转到上一个笔记位置
                                    setTimeout(function () {
                                        jumpNote();

                                    }, 100);
                                }, 600);
                                // console.log("start to jumpNote");
                                // localStorage.setItem("lastNotePos", i);
                                // localStorage.setItem("need_jump", true);

                            }
                        }, 1600);
                    }
                }, 100);
            });


        }

        // 如果localStorage中保存了上一个笔记
        // if (localStorage.getItem("lastNotePos")) {
        //     // 获取上一个笔记
        //     let lastPos = localStorage.getItem("lastNotePos");
        //     if (lastPos) {
        //         lastNote = noteItems[lastPos];
        //         // 获取是否需要跳转
        //         let need_jump = localStorage.getItem("need_jump");
        //         if (need_jump == "true") {
        //             lastNote.dispatchEvent(
        //                 new MouseEvent("click", {
        //                   clientX: 1,
        //                   clientY: 1,
        //                 })
        //               );
        //             // 跳转到上一个笔记位置
        //             setTimeout(function () {
        //                 jumpNote();
        //                 // 清除localStorage
        //                 localStorage.removeItem("lastNotePos");
        //                 localStorage.removeItem("need_jump");
        //             }, 100);
        //         }
        //     }

        // }

        // 底部添加笔记按钮

        if (invoke) {
            // 获取笔记图标
            let noteIcon = document.querySelector('.readerControls_item.note').querySelector('.icon');
            let backgroundImg = getComputedStyle(noteIcon).getPropertyValue("background-image");

            // 在readerBottomBar 的 rbb_item.setting(bar内第三个button) 后添加一个button
            let newInvoke = document.createElement("button");
            newInvoke.className = "rbb_item note";
            newInvoke.title = "笔记";
            newInvoke.innerHTML = '<span class="icon""></span><span class="txt">笔记</span>';

            invoke.insertBefore(newInvoke, invoke.children[3]);
            newInvoke.querySelector('.icon').style.backgroundImage = backgroundImg;
            // 设置点击事件为切换readerNotePanel的display
            newInvoke.addEventListener("click", function () {
                // 不隐藏readerBottomBar, 为readerBottomBar添加active class
                setTimeout(function () {
                    invoke.classList.add("active");

                }, 100);
                let notePanel = document.getElementsByClassName("readerNotePanel")[0];
                if (notePanel.style.display == "none") {
                    notePanel.style.display = "";
                } else {
                    notePanel.style.display = "none";
                }
                // 延迟100ms
                setTimeout(function () {
                    jumpNote();
                }, 100);
            });
        }
        // 监听点击事件(readerControls_item note)
        document.querySelector(".readerControls_item.note").addEventListener("click", function () {
            jumpNote();
        });


    }, 1500);
})();