Greasy Fork

Greasy Fork is available in English.

S1论坛帖子已读样式

已读标题变灰,帖子的url根据最新回复数会每次刷新

当前为 2020-07-22 提交的版本,查看 最新版本

// ==UserScript==
// @name         S1论坛帖子已读样式
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  已读标题变灰,帖子的url根据最新回复数会每次刷新
// @author       You
// @match        *.saraba1st.com/2b/forum*
// @match        *.saraba1st.com/2b/thread*
// @grant        none
// @run-at       document-body
// ==/UserScript==

function get(data, key) {
  const keys = key.replace(/\[(\d+)\]/g, ".$1").split(".");
  let result = data;
  while (keys.length && result) {
    result = result[keys.shift()];
  }
  return result;
}

function isThread() {
  return location.pathname.includes("thread");
}

function isThreadList() {
  return location.pathname.includes("forum");
}

function asyncRun(callback) {
  const timer = setInterval(() => {
    const ret = callback();
    if (ret) {
      clearInterval(timer);
    }
  }, 100);
}

function updateThreadReplyNum(id, num) {
  localStorage.setItem(id, num);
}

function getThreadLastReplyNum(id) {
  const num = localStorage.getItem(id);
  return num ? +num : null;
}

function appendStyle() {
  const style = document.createElement("style");
  style.type = "text/css";
  style.appendChild(
    document.createTextNode(
      ".tl th a:visited, .tl td.fn a:visited {color: #818588}"
    )
  );
  style.appendChild(
    document.createTextNode(
      ".tl th a:hover, .tl td.fn a:hover {color: #022C80}"
    )
  );
  document.body.appendChild(style);
}

(function () {
  "use strict";
  // 修改帖子样式
  appendStyle();

  // 动态修改url
  const hasReplacedIds = new Set();
  let table = null;
  let lastThreadNum = 0;
  let observer = null;

  function observeThreads() {
    const threads = Array.from(
      document.querySelectorAll("#threadlisttableid tbody tr")
    ).filter((element) => !hasReplacedIds.has(element.parentNode.id));
    threads.forEach((t) => observer.observe(t));
  }

  function initObserver() {
    observer = new IntersectionObserver(
      (entities) => {
        entities.forEach((entity) => {
          if (entity.isIntersecting) {
            const thread = entity.target;
            observer.unobserve(thread);

            const id = thread.parentNode.id;
            if (hasReplacedIds.has(id)) {
              return;
            }
            hasReplacedIds.add(id);

            // url
            const replyNum = +get(thread, "children[3].children[0].text");
            const title = get(thread, "children[1].children[2]");
            if (title && replyNum) {
              title.href += `#${replyNum}`;
            }

            // reply num
            const tid = get(id.match(/\d+/), "0");
            const lastReplyNum = +getThreadLastReplyNum(tid);
            if (lastReplyNum && replyNum && replyNum - lastReplyNum > 0) {
              title.textContent = `+${replyNum - lastReplyNum} ${
                title.textContent
              }`;
            }
          }
        });
      },
      {
        rootMargin: "100px",
      }
    );
  }

  if (isThreadList()) {
    initObserver();

    asyncRun(() => {
      table = document.getElementById("threadlisttableid");
      // 实际发现只检测table并不能保证帖子全加载了
      const nextPageBtn = document.querySelector("#autopbn");
      if (table && nextPageBtn) {
        lastThreadNum = table.childElementCount;
        observeThreads();
        return true;
      }
    });
    // 监控下一页
    asyncRun(() => {
      const nextPageBtn = document.querySelector("#autopbn");
      if (nextPageBtn) {
        nextPageBtn.addEventListener("click", () => {
          asyncRun(() => {
            if (table.childElementCount > lastThreadNum) {
              lastThreadNum = table.childElementCount;
              observeThreads();
              return true;
            }
          });
        });
        return true;
      }
    });

    // window.addEventListener('storage', (event) => {
    //     console.log(event.key,  event.newValue)

    // })
  }

  if (isThread()) {
    asyncRun(() => {
      if (window.tid) {
        const span = document.querySelector(
          "#postlist > table:nth-child(1) > tbody > tr > td.pls.ptn.pbn > div > span:nth-child(5)"
        );
        if (span) {
          updateThreadReplyNum(window.tid, span.textContent);
        }
        return true;
      }
    });
  }
})();