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

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

目前為 2023-08-28 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         微信读书笔记列表跟随当前章节滚动
// @namespace    http://tampermonkey.net/
// @version      0.4.3
// @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;
            }
        }
        // 隐藏推广按钮
        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.style.display = "none";
        }
        // 获取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 = appContent.getBoundingClientRect().top;
                    // 如果top 为-75,需检测是否有上一页,可能需要调用翻页并重新调用跳转笔记
                    console.log("appContentTop:" + appContentTop);
                    // TODO 考虑重构代码理清逻辑
                    if (appContentTop == -75) {
                        //    则判断为上一页,调用翻页并重新调用跳转笔记
                        console.log("start to judge if it is prev page");
                        // 可以考虑每个笔记跳转时都直接切换章节再跳转避免触发翻页bug
                        setTimeout(function () {
                            // 高度无变化,判断为需要切换上一页
                            if (appContentTop == -75) {
                                // 获取 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);
})();