Mark all sessions as read with one click!
// ==UserScript== // @name [Bilibili] MarkAsRead // @name:zh-CN [Bilibili] 一键已读 // @namespace ckylin-script-bilibili-mark-as-read // @version 0.6 // @description Mark all sessions as read with one click! // @description:zh-CN 一键设置所有会话已读! // @author CKylinMC // @match https://message.bilibili.com/* // @grant unsafeWindow // @supportURL https://github.com/CKylinMC/UserJS // @license GPL-3.0-only // ==/UserScript== if (typeof (unsafeWindow) === "undefined") var unsafeWindow = window; (function () { 'use strict'; const blacklist_elTitle = ["我的应援团","未关注人消息","疑似不良消息"]; const wait = t => new Promise(r => setTimeout(r, t)); const inBlacklist = el=>{ for(let titleItem of blacklist_elTitle){ if(el.querySelector(`[title='${titleItem}']`)) return true; } return false; } const touch = async el => { el.click(); await wait(100) }; const touchList = async div => { let active = div.querySelector(".active"); for (let el of [...div.children].splice(1)) { if (el.classList.contains("list-item") && el.querySelector(".notify") && !inBlacklist(el)) await touch(el) } if (active) await touch(active) else location.hash = "#/whisper"; }; const msgList = () => document.querySelector("div.list"); const asRead = async () => await touchList(msgList()); const settingList = () => document.querySelector("ul.list"); const intervalLog = { intervalId: null, lastHash: location.hash, lastState: false }; const intervalHashChecker = ()=>{ if(location.hash!==intervalLog.lastHash) { hashChecker(); intervalLog.lastHash = location.hash; } } const hashChecker = ()=>{ if(location.hash.startsWith("#/whisper")) { if(!intervalLog.lastState) { injectBtn(); intervalLog.lastState = true; } } else{ if(!intervalLog.lastState) return; let old; if (old = document.querySelector("#CKMARKREAD-BTN")) { old.style.transition = "margin .3s .2s, opacity .5s"; old.style.opacity = "0"; old.style.margin = "0px 0px"; setTimeout(()=>old.remove(),300); } intervalLog.lastState = false; } }; const waitFor = async (func, waitt = 100, retries = 100) => { while (--retries > 0) { try { const val = await func(); if (val) return val; await wait(waitt); } catch (e) { console.log(e); await wait(100); } } return false; }; const injectBtn = async () => { if (await waitFor(() => settingList())) { let old; if (old = document.querySelector("#CKMARKREAD-BTN")) old.remove(); const a = document.createElement("a"); a.href = "javascript:void(0)"; a.innerHTML = "💬 全部标为已读"; a.onclick = async (e) => { e.target.innerHTML = "🕓 请稍等..."; await waitFor(() => msgList()); await asRead(); e.target.innerHTML = "✔ 已标为已读"; e.target.onclick = e => e.target.innerHTML = "✔ 无需操作"; setTimeout(()=>{ e.target.parentElement.style.transition = "margin .3s .2s, opacity .5s"; e.target.parentElement.style.opacity = "0"; e.target.parentElement.style.margin = "0px 0px"; setTimeout(()=>e.target.parentElement.remove(),300); },3000); }; const item = document.createElement("li"); item.classList.add("item"); item.id = "CKMARKREAD-BTN"; item.style.opacity = "0"; item.style.margin = "0px 0"; item.style.transition = "all .3s"; item.appendChild(a); settingList().appendChild(item); setTimeout(()=>{ if(item){ item.style.margin = "15px 0"; item.style.opacity = "1"; } },50) } }; const delayedInjectTask = async () => { await wait(1000); hashChecker(); if(intervalLog.intervalId)clearInterval(intervalLog.intervalId); intervalLog.intervalId = setInterval(intervalHashChecker,300); }; delayedInjectTask(); })();