// ==UserScript==
// @name 98堂-预览
// @version 1.8.4
// @namespace https://sleazyfork.org/zh-CN/users/1461640-%E6%98%9F%E5%AE%BF%E8%80%81%E9%AD%94
// @author 星宿老魔
// @description 98堂[原色花堂]自动预览帖子中的图片及链接,支持无缝翻页。
// @match https://sehuatang.org/*
// @match https://sehuatang.net/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=sehuatang.org
// @license MIT
// @grant none
// @run-at document-start
// ==/UserScript==
(function(){"use strict";const f={defaults:{maxPreviewImages:3,concurrencyLimit:5,cacheEnabled:!0,cacheSize:50,cacheTTL:6e5,lazyLoadThreshold:2,networkTimeout:5e3},get(d){return JSON.parse(localStorage.getItem("SHT_PREVIEW_CONFIG")||"{}")[d]??this.defaults[d]},set(d,e){const t=JSON.parse(localStorage.getItem("SHT_PREVIEW_CONFIG")||"{}");t[d]=e,localStorage.setItem("SHT_PREVIEW_CONFIG",JSON.stringify(t))},getAll(){const d=JSON.parse(localStorage.getItem("SHT_PREVIEW_CONFIG")||"{}");return{...this.defaults,...d}}};class h{static injected=!1;static inject(){if(this.injected)return;const e=document.createElement("style");e.textContent='.sht-panel{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:360px;background:#f4f4f4;border-radius:6px;box-shadow:0 5px 20px rgba(0,0,0,0.2);z-index:10001;font-family:sans-serif;display:none;flex-direction:column}.sht-header{padding:16px 20px;font-size:16px;font-weight:600;color:#333;background:#e9e9e9;border-bottom:1px solid #ddd;border-radius:6px 6px 0 0;cursor:move;user-select:none}.sht-content{padding:20px}.sht-row{display:flex;align-items:center;justify-content:space-between;margin-bottom:15px}.sht-label{font-size:14px;color:#555}.sht-select{padding:8px 12px;border-radius:5px;border:1px solid #ccc;font-size:14px;cursor:pointer;background:white;min-width:120px}.sht-footer{display:flex;justify-content:flex-end;padding:15px 20px;background:#e9e9e9;border-top:1px solid #ddd;border-radius:0 0 6px 6px}.sht-btn{padding:8px 16px;border:none;border-radius:5px;font-size:14px;cursor:pointer}.sht-btn-primary{background:#4d84c6;color:white}.sht-btn-secondary{background:#ccc;color:#333;margin-left:10px}.sht-close{position:absolute;top:16px;right:16px;width:32px;height:32px;border:none;border-radius:50%;background:rgba(0,0,0,0.1);color:#333;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:18px}.sht-card{position:relative;padding:15px;border:1px solid #e0e0e0;border-radius:6px;margin:20px;background:#fff;width:calc(100% - 40px);box-sizing:border-box}.sht-img-grid{display:flex;flex-wrap:nowrap;align-items:flex-start;gap:8px;width:100%}.sht-img-item{overflow:hidden;border-radius:4px;position:relative;cursor:pointer;height:160px}.sht-img{width:100%;height:100%;object-fit:cover}.sht-links{margin:10px 0;padding:8px;background:#f8f9fa;border:1px solid #e0e0e0;border-radius:4px;width:100%;box-sizing:border-box}.sht-link-title{font-weight:bold;margin-bottom:6px;font-size:13px}.sht-link-item{background:white;border:1px solid #ddd;padding:4px;border-radius:3px;margin-bottom:4px;word-break:break-all;cursor:pointer;font-size:12px}.sht-nav-toggle{position:relative;display:inline-block;width:38px;height:20px}.sht-nav-toggle input{opacity:0;width:0;height:0}.sht-nav-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:#ddd;border-radius:10px}.sht-nav-slider:before{position:absolute;content:"";height:16px;width:16px;left:2px;bottom:2px;background:white;border-radius:50%;box-shadow:0 1px 3px rgba(0,0,0,0.2)}.sht-nav-toggle input:checked+.sht-nav-slider{background:#4d84c6}.sht-nav-toggle input:checked+.sht-nav-slider:before{transform:translateX(18px)}.sht-restore{position:fixed;right:0;bottom:10px;z-index:9997;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px 5px;border-radius:5px 0 0 5px;box-shadow:-1px 1px 5px rgba(0,0,0,0.2);background:rgba(50,50,50,0.7);border:none;box-sizing:border-box;cursor:pointer;color:white;font-size:11px;letter-spacing:2px;writing-mode:vertical-rl;text-orientation:mixed}',document.head.appendChild(e),this.injected=!0}static createElement(e,t,n){const i=document.createElement(e);return t&&(i.className=t),n&&(i.textContent=n),i}static setImageGridWidth(e,t){const i=`calc((100% - ${(t-1)*8}px) / ${t})`;Array.from(e.children).forEach(a=>{a.style.width=i,a.style.flex="0 0 auto"})}}class ${static create(e,t=[]){const n=document.createElement("div");n.style.cssText="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.9); display: flex; justify-content: center; align-items: center; z-index: 9999; cursor: pointer;";const i=document.createElement("img");if(i.src=e,i.style.cssText="max-width: 90%; max-height: 90%; object-fit: contain; border: 2px solid white;",n.appendChild(i),t.length>1){let a=t.indexOf(e);const s=()=>{o.style.display=a>0?"flex":"none",r.style.display=a<t.length-1?"flex":"none",c.textContent=`${a+1} / ${t.length}`},o=document.createElement("div");o.innerHTML="‹",o.style.cssText="position: absolute; left: 20px; top: 50%; transform: translateY(-50%); width: 50px; height: 50px; background-color: rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 30px; color: white; cursor: pointer; z-index: 10000;",o.addEventListener("click",l=>{l.stopPropagation(),a>0&&(a--,i.src=t[a],s())}),n.appendChild(o);const r=document.createElement("div");r.innerHTML="›",r.style.cssText="position: absolute; right: 20px; top: 50%; transform: translateY(-50%); width: 50px; height: 50px; background-color: rgba(255, 255, 255, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 30px; color: white; cursor: pointer; z-index: 10000;",r.addEventListener("click",l=>{l.stopPropagation(),a<t.length-1&&(a++,i.src=t[a],s())}),n.appendChild(r);const c=document.createElement("div");c.style.cssText="position: absolute; top: 20px; left: 50%; transform: translateX(-50%); background-color: rgba(0, 0, 0, 0.7); color: white; padding: 8px 16px; border-radius: 20px; font-size: 14px; z-index: 10000;",n.appendChild(c),s()}n.addEventListener("click",a=>{a.target!==i&&!a.target?.closest('div[style*="position: absolute"]')&&document.body.removeChild(n)}),document.body.appendChild(n)}}class N{static panelInstance=null;static create(){if(document.getElementById("sht-config-panel"))return document.getElementById("sht-config-panel");h.inject();const e=h.createElement("div","sht-panel");e.id="sht-config-panel";const t=h.createElement("div","sht-header","预览图设置"),n=h.createElement("button","sht-close","×");n.addEventListener("click",()=>e.style.display="none"),t.appendChild(n),e.appendChild(t);const i=h.createElement("div","sht-content");e.appendChild(i);const a=(c,l,p)=>{const u=h.createElement("div","sht-row"),g=h.createElement("label","sht-label",c),y=h.createElement("select","sht-select");y.id=`config-${l}`;const w=f.getAll()[l];return p.forEach(A=>{const I=document.createElement("option");I.value=A.value.toString(),I.textContent=A.label,A.value===w&&(I.selected=!0),y.appendChild(I)}),u.appendChild(g),u.appendChild(y),u};i.appendChild(a("最大预览图数量:","maxPreviewImages",[{value:3,label:"3张 (推荐)"},{value:4,label:"4张 (适中)"},{value:5,label:"5张 (较多)"}])),i.appendChild(a("并发加载数量:","concurrencyLimit",[{value:3,label:"3个 (保守)"},{value:5,label:"5个 (推荐)"},{value:8,label:"8个 (激进)"}]));const s=h.createElement("div","sht-footer"),o=h.createElement("button","sht-btn sht-btn-primary","保存设置"),r=h.createElement("button","sht-btn sht-btn-secondary","取消");return o.addEventListener("click",()=>{f.set("maxPreviewImages",parseInt(document.getElementById("config-maxPreviewImages").value,10)),f.set("concurrencyLimit",parseInt(document.getElementById("config-concurrencyLimit").value,10)),e.style.display="none",window.location.reload()}),r.addEventListener("click",()=>e.style.display="none"),s.appendChild(o),s.appendChild(r),e.appendChild(s),document.body.appendChild(e),this.makeDraggable(e,t),this.panelInstance=e,e}static makeDraggable(e,t){let n=!1,i,a;t.addEventListener("mousedown",s=>{n=!0,i=s.clientX-e.offsetLeft,a=s.clientY-e.offsetTop,t.style.cursor="grabbing"}),document.addEventListener("mousemove",s=>{n&&(e.style.left=`${s.clientX-i}px`,e.style.top=`${s.clientY-a}px`)}),document.addEventListener("mouseup",()=>{n=!1,t.style.cursor="move"})}static show(){this.panelInstance&&(this.panelInstance.style.display="flex")}}class x{static createLinksElement(e){if(e.ed2k.length===0&&e.magnet.length===0&&e.xunlei.length===0&&e.baidu.length===0)return null;const t=h.createElement("div","sht-links"),n=(a,s,o)=>{if(s.length===0)return;const r=h.createElement("div","sht-link-title",a);o||(r.style.marginTop="15px"),t.appendChild(r),s.forEach((c,l)=>{const p=document.createElement("div");p.style.marginBottom="10px";const u=h.createElement("div","sht-link-item",c);u.title="点击复制链接",u.addEventListener("click",g=>{g.preventDefault(),g.stopPropagation(),navigator.clipboard.writeText(c).catch(()=>{})}),p.appendChild(u),l>0&&(p.style.display="none",p.classList.add("hidden-link")),t.appendChild(p)})};n("ED2K链接:",e.ed2k,!0),n("磁力链接:",e.magnet,!1),n("迅雷网盘:",e.xunlei,!1),n("百度网盘:",e.baidu,!1);const i=e.ed2k.length+e.magnet.length+e.xunlei.length+e.baidu.length;if(i>1){const a=document.createElement("button");a.textContent=`显示剩余 ${i-1} 个链接`,a.style.cssText="margin-top: 5px; cursor: pointer; border: 1px solid #ccc; background-color: #f0f0f0; padding: 5px 10px; border-radius: 4px;";let s=!1;a.addEventListener("click",o=>{o.preventDefault(),o.stopPropagation(),s=!s,t.querySelectorAll(".hidden-link").forEach(r=>{r.style.display=s?"block":"none"}),a.textContent=s?"收起链接":`显示剩余 ${i-1} 个链接`}),t.appendChild(a)}return t}static createNormalPageToggle(e){const t=document.querySelector("#nv ul");if(!t)return;N.create();const n=document.createElement("li");n.style.display="flex",n.style.alignItems="center";const i=document.createElement("div");i.id="nav-toggle-infinite-scroll";const a=document.createElement("a");a.href="javascript:;",a.textContent="无缝翻页",i.appendChild(a),n.appendChild(i);const s=document.createElement("a");s.href="javascript:;",s.textContent="预览图设置",s.title="预览图设置",s.style.cssText="margin-left: 8px; text-decoration: none;",s.addEventListener("click",c=>{c.preventDefault(),c.stopPropagation(),N.show()}),n.appendChild(s),t.appendChild(n);let o=localStorage.getItem(e.storageKeyEnabled)===null?e.defaultEnabled||!1:localStorage.getItem(e.storageKeyEnabled)==="true";const r=()=>{o?(i.classList.add("a"),a.style.cssText=`
background-color: #840000 !important;
background-image: url(/static/image/common/nv_a.png) !important;
background-repeat: no-repeat !important;
background-position: 50% -33px !important;
color: #fff !important;
font-weight: 700 !important;
height: 33px !important;
line-height: 33px !important;
padding: 0 8px !important;
`):(i.classList.remove("a"),i.classList.remove("hover"),a.style.cssText="")};i.addEventListener("click",c=>{c.preventDefault(),o=!o,localStorage.setItem(e.storageKeyEnabled,String(o)),r(),o?e.onEnable():e.onDisable()}),r(),o&&e.onEnable()}static createSearchPageSingleToggle(e){const t=document.querySelector(".sttl.mbn");if(!t)return;t.style.display="flex",t.style.justifyContent="space-between",t.style.alignItems="center";const n=document.createElement("div");n.style.display="flex",n.style.alignItems="center";const i=document.createElement("div");i.style.display="flex",i.style.alignItems="center";const a=document.createElement("span");a.textContent="无缝翻页:",a.style.cssText="font-size: 13px; color: #666; margin-right: 6px; line-height: 20px;",i.appendChild(a);const s=h.createElement("label","sht-nav-toggle"),o=document.createElement("input");o.type="checkbox";const r=h.createElement("span","sht-nav-slider");s.appendChild(o),s.appendChild(r),i.appendChild(s);let c=localStorage.getItem(e.storageKeyEnabled)===null?e.defaultEnabled||!1:localStorage.getItem(e.storageKeyEnabled)==="true";o.addEventListener("change",()=>{c=o.checked,localStorage.setItem(e.storageKeyEnabled,String(c)),c?e.onEnable():e.onDisable()}),o.checked=c,c&&e.onEnable(),n.appendChild(i),t.appendChild(n)}static createSearchPageDualToggles(e,t){const n=document.querySelector(".sttl.mbn");if(!n)return;n.style.display="flex",n.style.justifyContent="space-between",n.style.alignItems="center";const i=document.createElement("div");i.style.display="flex",i.style.alignItems="center",i.style.gap="20px";const a=(s,o)=>{const r=document.createElement("div");r.style.display="flex",r.style.alignItems="center";const c=document.createElement("span");c.textContent=`${s}:`,c.style.cssText="font-size: 13px; color: #666; margin-right: 6px; line-height: 20px;",r.appendChild(c);const l=h.createElement("label","sht-nav-toggle"),p=document.createElement("input");p.type="checkbox";const u=h.createElement("span","sht-nav-slider");l.appendChild(p),l.appendChild(u),r.appendChild(l);let g=localStorage.getItem(o.storageKeyEnabled)===null?o.defaultEnabled||!1:localStorage.getItem(o.storageKeyEnabled)==="true";return p.addEventListener("change",()=>{g=p.checked,localStorage.setItem(o.storageKeyEnabled,String(g)),g?o.onEnable():o.onDisable()}),p.checked=g,g&&o.onEnable(),r};i.appendChild(a("无缝翻页",e)),i.appendChild(a("移除隐藏贴",t)),n.appendChild(i)}static createFixedRestoreButton(e){window.activeRestoreButton&&window.activeRestoreButton.remove();const t=h.createElement("div","sht-restore");return t.id=e.id,t.innerHTML=e.labelHtml,t.addEventListener("click",e.onClick),document.body.appendChild(t),window.activeRestoreButton=t,t}static createUnifiedInfoCard(e,t,n,i,a){e.innerHTML="",e.className="sht-card";const s=document.createElement("a");let o=t.textContent||"预览";if(o=o.replace(/\s+/g," ").trim(),s.textContent=o,s.href=t.href,s.target="_blank",s.style.cssText="font-size: 16px; font-weight: bold; color: #2c5aa0; margin-bottom: 15px; line-height: 1.4; cursor: pointer; text-decoration: underline; display: block;",s.addEventListener("click",c=>{!c.ctrlKey&&!c.metaKey&&!c.shiftKey&&(c.preventDefault(),window.open(t.href,"_blank"))}),e.appendChild(s),n.length>0){const c=h.createElement("div","sht-img-grid");n.forEach(l=>{const p=l.getAttribute("file"),u=h.createElement("div","sht-img-item"),g=h.createElement("img","sht-img");g.src=p,u.addEventListener("click",y=>{y.preventDefault(),y.stopPropagation(),$.create(p,n.map(w=>w.getAttribute("file")))}),u.appendChild(g),c.appendChild(u)}),h.setImageGridWidth(c,n.length),e.appendChild(c)}const r=this.createLinksElement(i);r&&(r.className="sht-links",e.appendChild(r))}}class m{static PREFIX="[98堂]";static debug(e){}static info(e){console.log(`${this.PREFIX} ${e}`)}static error(e,t){console.error(`${this.PREFIX} ${e}`,t||"")}static summary(e,t){const n=Object.entries(t).filter(([i,a])=>a>0).map(([i,a])=>`${i}:${a}`);n.length>0&&console.log(`${this.PREFIX} ${e} ${n.join(" ")}`)}}class C{limit;queue=[];activeCount=0;constructor(e){this.limit=e}async addTask(e){return new Promise((t,n)=>{this.queue.push({task:e,resolve:t,reject:n}),this._next()})}_next(){if(this.activeCount>=this.limit||this.queue.length===0)return;this.activeCount++;const{task:e,resolve:t,reject:n}=this.queue.shift();e().then(t,n).finally(()=>{this.activeCount--,this._next()})}}class H{cache=new Map;maxSize=50;normalTtl=600*1e3;highTtl=1800*1e3;set(e,t,n="normal"){if(this.cleanup(),this.cache.size>=this.maxSize){for(const[i,a]of this.cache.entries())if(a.priority==="normal"){this.cache.delete(i);break}}this.cache.set(e,{data:t,timestamp:Date.now(),priority:n})}get(e){const t=this.cache.get(e);if(!t)return null;const n=t.priority==="high"?this.highTtl:this.normalTtl;return Date.now()-t.timestamp>n?(this.cache.delete(e),null):t.data}has(e){const t=this.cache.get(e);if(!t)return!1;const n=t.priority==="high"?this.highTtl:this.normalTtl;return Date.now()-t.timestamp>n?(this.cache.delete(e),!1):!0}cleanup(){const e=Date.now();for(const[t,n]of this.cache.entries()){const i=n.priority==="high"?this.highTtl:this.normalTtl;e-n.timestamp>i&&this.cache.delete(t)}}clear(){this.cache.clear()}size(){return this.cleanup(),this.cache.size}}const L=new H;async function q(d,e={}){const{timeout:t=5e3,...n}=e,i=new AbortController,a=setTimeout(()=>i.abort(),t);try{const s=await fetch(d,{...n,signal:i.signal});return clearTimeout(a),s}catch(s){throw clearTimeout(a),s}}async function v(d,e="normal"){const t=L.get(d);if(t)return t;try{const i=await(await q(d)).text(),s=new DOMParser().parseFromString(i,"text/html"),o=_(s);return L.set(d,o,e),o}catch(n){return m.error("获取失败:",n),null}}function R(d,e){let t;return((...n)=>{clearTimeout(t),t=window.setTimeout(()=>d(...n),e)})}function D(d,e){let t=0;return((...n)=>{const i=Date.now();i-t>=e&&(d(...n),t=i)})}class b{static extractAllLinks(e){const t={ed2k:[],magnet:[],xunlei:[],baidu:[]};try{this.extractResourceLinks(e,t),this.extractHtmlNetworkDiskLinks(e,t),this.extractCodeBlockLinks(e,t),t.magnet.length===0&&this.extractMagnetFromFullPage(e,t),this.deduplicateLinks(t),m.summary("提取完成",{磁力:t.magnet.length,ED2K:t.ed2k.length,迅雷:t.xunlei.length,百度:t.baidu.length})}catch(n){m.error("链接提取错误",n)}return t}static extractResourceLinks(e,t){e.querySelectorAll('a[href^="magnet:"], a[href^="ed2k:"]').forEach(a=>{const s=a.href;s&&this.categorizeLink(s,t)}),e.querySelectorAll('a[href*="ed2k://"], a[href*="magnet:"]').forEach(a=>{const s=a.href;s&&this.categorizeLink(s,t)});const i=(e.body.textContent||"").match(/ed2k:\/\/\|file\|[^|]+\|\d+\|[A-F0-9]+\|\//gi);i&&i.forEach(a=>t.ed2k.push(a.trim()))}static extractHtmlNetworkDiskLinks(e,t){e.querySelectorAll('a[href*="pan.xunlei.com/s/"], a[href*="pan.baidu.com/s/"]').forEach(n=>{const i=n.getAttribute("href");i&&(i.includes("pan.xunlei.com/s/")?t.xunlei.push(this.combineNetworkDiskLink(n,i)):i.includes("pan.baidu.com/s/")&&t.baidu.push(this.combineNetworkDiskLink(n,i)))})}static extractCodeBlockLinks(e,t){e.querySelectorAll(".blockcode").forEach(n=>{const i=n.textContent||"",a=i.match(/magnet:\?xt=urn:btih:[a-fA-F0-9]{40}/g);if(a)a.forEach(r=>t.magnet.push(r.trim()));else{const r=i.match(/\b([a-fA-F0-9]{40})\b/g);r&&r.length<=3&&r.forEach(c=>t.magnet.push(`magnet:?xt=urn:btih:${c}`))}const s=i.match(/https:\/\/pan\.xunlei\.com\/s\/[a-zA-Z0-9_-]+/g);s&&s.forEach(r=>t.xunlei.push(r.trim()));const o=i.match(/https:\/\/pan\.baidu\.com\/s\/[a-zA-Z0-9_-]+/g);o&&o.forEach(r=>t.baidu.push(r.trim()))})}static extractMagnetFromFullPage(e,t){const n=e.querySelector(".t_f, #postmessage, .pcb"),i=n?n.textContent||"":e.body.textContent||"",a=i.match(/magnet:\?xt=urn:btih:[a-fA-F0-9]{40}/g);if(a)a.forEach(s=>t.magnet.push(s.trim()));else{const s=i.match(/\b([a-fA-F0-9]{40})\b/g);s&&s.slice(0,3).forEach(o=>t.magnet.push(`magnet:?xt=urn:btih:${o}`))}}static categorizeLink(e,t){e.startsWith("ed2k://")?t.ed2k.push(e):e.startsWith("magnet:")?t.magnet.push(e):e.includes("pan.xunlei.com")?t.xunlei.push(e):e.includes("pan.baidu.com")&&t.baidu.push(e)}static deduplicateLinks(e){e.ed2k=[...new Set(e.ed2k)],e.magnet=[...new Set(e.magnet)],e.xunlei=[...new Set(e.xunlei)],e.baidu=[...new Set(e.baidu)]}static hasAnyContent(e){return e.ed2k.length>0||e.magnet.length>0||e.xunlei.length>0||e.baidu.length>0}static combineNetworkDiskLink(e,t){if(t.includes("?pwd="))return t;const n=(e.parentElement?.textContent||"").match(/提取码[::]\s*([a-zA-Z0-9]+)/);return n?`${t}?pwd=${n[1]}`:t}}function M(d){return b.extractAllLinks(d)}function _(d){const e=Array.from(d.querySelectorAll("img.zoom")).filter(n=>{const i=n.getAttribute("file");return!i||i.includes("static")||parseInt(n.getAttribute("width")||"0")===430?!1:!(i.toLowerCase().endsWith(".png")&&(i.includes("7pzzv.us")||i.includes("iili.io")))}),t=M(d);return{images:e,links:t}}const U=Object.freeze(Object.defineProperty({__proto__:null,ConcurrencyManager:C,LinkExtractor:b,Logger:m,PreviewCache:H,debounce:R,extractDownloadLinks:M,extractPostPreviewData:_,fetchWithCache:v,fetchWithTimeout:q,previewCache:L,throttle:D},Symbol.toStringTag,{value:"Module"}));class T{static applyInitialStickPostHiding(){setTimeout(()=>{this.applyStickPostHiding()},100)}static applyStickPostHidingToNewContent(){this.hideStickPostsAndAdminPosts(":not(.hide-processed)",!0)}static applyDefaultTimeSort(){const e=window.location.href,t=new URLSearchParams(window.location.search),n=t.get("mod"),i=t.get("fid");(n==="forumdisplay"&&i||/forum-\d+-\d+\.html/.test(e))&&t.get("orderby")!=="dateline"&&this.redirectToTimeSortedPage(e,n,i)}static applyStickPostHiding(){this.hideStickPostsAndAdminPosts("",!1)}static hideStickPostsAndAdminPosts(e,t){document.querySelectorAll(`#threadlisttableid tbody[id^="stickthread_"]${e}`).forEach(n=>{n.style.display="none",t&&n.classList.add("hide-processed")}),document.querySelectorAll(`#threadlisttableid tbody[id^="normalthread_"]${e}`).forEach(n=>{const i=n.querySelector("em a");i&&i.textContent?.includes("版务管理")&&(n.style.display="none"),t&&n.classList.add("hide-processed")})}static redirectToTimeSortedPage(e,t,n){let i;if(t==="forumdisplay"&&n){const a=new URL(e);a.searchParams.set("orderby","dateline"),a.searchParams.set("filter","author"),i=a.href}else{const a=e.match(/forum-(\d+)-(\d+)\.html/);if(a){const s=a[1],o=a[2];i=`forum.php?mod=forumdisplay&fid=${s}&page=${o}&orderby=dateline&filter=author`}else return}window.location.href=i}}class z{static async processSingleThread(e){const t=e.href,n=e.closest("tbody");if(!(!n||n.nextElementSibling?.id==="imagePreviewTbody"||n.querySelector(".searchImagePreview")||n.dataset.previewProcessed==="true")){n.dataset.previewProcessed="true";try{const i=await v(t);if(!i)return;const{images:a,links:s}=i,o=a.slice(0,f.get("maxPreviewImages"));if(o.length===0&&!b.hasAnyContent(s))return;this.renderSimpleThreadContent(e,n,o,s,t)}catch(i){m.error("处理失败:",i),n&&(n.dataset.previewProcessed="false")}}}static renderSimpleThreadContent(e,t,n,i,a){h.inject();const s=e.closest("tr");s&&(s.style.display="none");const o=document.createElement("div");x.createUnifiedInfoCard(o,e,n,i,a);const r=document.createElement("tbody");r.id="imagePreviewTbody";const c=document.createElement("tr"),l=document.createElement("td");l.colSpan=5,l.style.cssText="padding: 0; border: 0;",l.appendChild(o),c.appendChild(l),r.appendChild(c),t.after(r)}static async displayInitialThreads(){const e=document.querySelectorAll("#threadlisttableid .s.xst"),t=new C(f.get("concurrencyLimit")),n=Array.from(e).map(i=>t.addTask(async()=>{i.closest("th, td")?.querySelector("em a")?.textContent?.includes("版务管理")||await this.processSingleThread(i)}));await Promise.all(n)}static async processNewThreads(e){const t=Array.from(e.querySelectorAll("tbody[id^=normalthread_]:not(.processed) a.s.xst"));e.querySelectorAll(".processed").length,await Promise.all(t.map((n,i)=>{const a=n.closest("tbody");return a?.classList.add("processed"),a?.querySelector("em a")?.textContent?.includes("版务管理")?Promise.resolve():this.processSingleThread(n)}))}}class E{static pageNumDisplay=null;static createPageNumElement(){document.getElementById("page-number-display")||(this.pageNumDisplay=document.createElement("div"),this.pageNumDisplay.id="page-number-display",this.pageNumDisplay.style.cssText="position: fixed; z-index: 9998; user-select: none; display: none; background-color: rgba(50,50,50,0.5); color: white; padding: 5px; border-radius: 5px; font-size: 12px; text-align: center;",document.body.appendChild(this.pageNumDisplay))}static updateAndSaveForumState(){this.updateFloatingPageNumber(),this.saveForumState()}static updateFloatingPageNumber(){if(!this.pageNumDisplay)return;const e=document.getElementById("scrolltop");if(e&&e.offsetHeight>0&&window.getComputedStyle(e).visibility!=="hidden"){const t=e.getBoundingClientRect();this.pageNumDisplay.style.display="block",this.pageNumDisplay.style.top=`${t.top-this.pageNumDisplay.offsetHeight-5}px`,this.pageNumDisplay.style.left=`${t.left}px`,this.pageNumDisplay.style.width=`${t.width}px`,this.pageNumDisplay.style.boxSizing="border-box";const n=document.querySelector(".pg strong")?.textContent||"1";this.pageNumDisplay.textContent=`第${n}页`}else this.pageNumDisplay.style.display="none"}static saveForumState(){const e=document.querySelector("#pt .z a:last-of-type")?.textContent,t=document.querySelector(".pg strong")?.textContent||"1";if(e){const n=document.querySelector('.pg a[href*="page="]')||document.querySelector('.pg a[href*="-"]');let i=null;n&&(i=n.href.replace(/([?&]page=)\d+/,"$1__PAGE__").replace(/-\d+\.html/,"-__PAGE__.html")),localStorage.setItem("lastForumState",JSON.stringify({sectionName:e,page:t,urlTemplate:i}))}}static setupForumRestore(){const e=JSON.parse(localStorage.getItem("lastForumState")||"null"),t=document.querySelector("#pt .z a:last-of-type")?.textContent,n=parseInt(new URLSearchParams(window.location.search).get("page")||window.location.pathname.match(/-(\d+)\.html$/)?.[1]||"1",10);if(e&&e.sectionName&&e.urlTemplate){const i=e.sectionName===t,a=parseInt(e.page,10)>n;if(!i||i&&a){const s=`<span style="writing-mode: vertical-rl; text-orientation: mixed; font-size: 11px; color: white; letter-spacing: 2px;">恢复: ${e.sectionName} (${e.page})</span>`;window.activeRestoreButton=x.createFixedRestoreButton({id:"restore-forum-btn",labelHtml:s,onClick:()=>{const o=e.urlTemplate.replace("__PAGE__",e.page);window.location.href=o}})}}}static setupStateTracking(){const e=D(()=>this.updateAndSaveForumState(),100);window.addEventListener("scroll",e,{passive:!0}),window.addEventListener("resize",e,{passive:!0});const t=document.getElementById("scrolltop");t&&new MutationObserver(e).observe(t,{attributes:!0,attributeFilter:["style","class"]})}}class k{static scrollHandler=null;static isLoading=!1;static nextUrl="";static loadingIndicator=null;static threadRenderer=null;static settingsApplier=null;static forumStateManager=null;static setDependencies(e){this.threadRenderer=e.threadRenderer,this.settingsApplier=e.settingsApplier,this.forumStateManager=e.forumStateManager}static enableInfiniteScroll(){if(this.scrollHandler)return;const e=document.querySelector(".pg a.nxt");if(e)this.nextUrl=e.href;else return;this.createLoadingIndicator(),this.setupScrollListener(),this.forumStateManager?.updateAndSaveForumState()}static disableInfiniteScroll(){this.scrollHandler&&(window.removeEventListener("scroll",this.scrollHandler),this.scrollHandler=null),this.loadingIndicator&&(this.loadingIndicator.style.display="none"),this.forumStateManager?.updateAndSaveForumState(),this.redirectToCurrentPage()}static createLoadingIndicator(){this.loadingIndicator||(this.loadingIndicator=document.createElement("div"),this.loadingIndicator.textContent="正在加载更多内容...",this.loadingIndicator.style.cssText="text-align: center; padding: 20px; display: none;",document.querySelector("#threadlist")?.insertAdjacentElement("afterend",this.loadingIndicator))}static setupScrollListener(){this.scrollHandler=async()=>{this.isLoading||!this.nextUrl||document.documentElement.scrollTop+document.documentElement.clientHeight>=document.documentElement.scrollHeight-500&&await this.loadNextPage()},window.addEventListener("scroll",this.scrollHandler,{passive:!0})}static async loadNextPage(){this.isLoading=!0,this.loadingIndicator&&(this.loadingIndicator.style.display="block");try{const t=await(await fetch(this.nextUrl)).text(),i=new DOMParser().parseFromString(t,"text/html"),a=document.querySelector("table#threadlisttableid"),s=i.querySelectorAll("table#threadlisttableid > tbody[id^=normalthread_]");s.length>0&&a&&(await this.appendNewContent(a,s),this.updatePagination(i)),this.updateNextPageUrl()}catch(e){m.error("翻页失败:",e),this.loadingIndicator&&(this.loadingIndicator.textContent="加载失败")}finally{this.isLoading=!1,this.updateLoadingIndicator(),this.forumStateManager?.updateAndSaveForumState()}}static async appendNewContent(e,t){const n=document.createDocumentFragment();t.forEach(i=>n.appendChild(i)),e.appendChild(n),this.threadRenderer&&await this.threadRenderer.processNewThreads(e),this.settingsApplier&&this.settingsApplier.applyStickPostHidingToNewContent()}static updatePagination(e){const t=e.querySelector(".pg"),n=document.querySelector(".pg");n&&t&&n.replaceWith(t)}static updateNextPageUrl(){const e=document.querySelector(".pg a.nxt");this.nextUrl=e?e.href:""}static updateLoadingIndicator(){this.loadingIndicator&&(this.nextUrl?this.loadingIndicator.style.display="none":this.loadingIndicator.textContent="已加载全部内容")}static redirectToCurrentPage(){const e=parseInt(document.querySelector(".pg strong")?.textContent||"1",10);if(isNaN(e))window.location.reload();else{const t=new URL(window.location.href);t.searchParams.set("page",e.toString()),window.location.href=t.toString()}}}class O{static init(){E.createPageNumElement(),E.setupForumRestore(),E.setupStateTracking(),k.setDependencies({threadRenderer:z,settingsApplier:T,forumStateManager:E}),this.setupToggle(),z.displayInitialThreads(),T.applyInitialStickPostHiding(),T.applyDefaultTimeSort()}static setupToggle(){x.createNormalPageToggle({storageKeyEnabled:"normalPageInfiniteScroll",onEnable:()=>k.enableInfiniteScroll(),onDisable:()=>k.disableInfiniteScroll(),defaultEnabled:!1})}}class j{static updateAndSaveSearchState(){const e=document.querySelector(".sttl .emfont")?.textContent;if(e){let t="1";const n=document.querySelector(".pg strong");if(n)t=n.textContent||"1";else if(!document.querySelector(".pg a.nxt")){const s=window.location.href.match(/[?&]page=(\d+)/);s&&(t=s[1])}const i=new URLSearchParams(window.location.search);i.delete("page");const a=window.location.pathname+"?"+i.toString();localStorage.setItem("lastSearchState",JSON.stringify({keyword:e,page:t,baseUrl:a}))}}static setupSearchRestore(){const e=JSON.parse(localStorage.getItem("lastSearchState")||"null"),t=document.querySelector(".sttl .emfont")?.textContent,n=parseInt(new URLSearchParams(window.location.search).get("page")||"1",10);if(e&&e.keyword){const i=e.keyword===t,a=parseInt(e.page,10)>n;if(!i||i&&a){const s=`<span style="writing-mode: vertical-rl; text-orientation: mixed; font-size: 11px; color: white; letter-spacing: 2px;">恢复: ${e.keyword} (${e.page})</span>`;window.activeRestoreButton=x.createFixedRestoreButton({id:"restore-search-btn",labelHtml:s,onClick:()=>{window.location.href=`${e.baseUrl}&page=${e.page}`}})}}}}class F{static applyStickyLayout(){const e=document.getElementById("ct");if(!e)return;const t=document.getElementById("toptb"),n=e.querySelector("form.searchform"),i=e.querySelector(".tl");if(!i)return;const a=i.querySelector(".sttl"),s=i.querySelector("#threadlist"),o=i.querySelector(".pgs"),r=document.getElementById("ft");if(!s)return;r&&r.remove();const c=document.createElement("div");t&&c.appendChild(t),n&&c.appendChild(n),a&&c.appendChild(a);const l=document.createElement("div");l.id="sticky-scroll-container",l.appendChild(s);const p=document.createElement("div");o&&p.appendChild(o),e.innerHTML="",e.appendChild(c),e.appendChild(l),e.appendChild(p),this.injectLayoutStyles()}static injectLayoutStyles(){const e=document.createElement("style");e.textContent=`
html, body { height: 100%; overflow: hidden; margin: 0; }
#ct { height: 100% !important; display: flex; flex-direction: column; }
#ct > div:nth-child(1) { flex-shrink: 0; overflow: hidden; }
#sticky-scroll-container { flex-grow: 1; overflow-y: auto; border-top: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0; position: relative; }
#ct > div:nth-child(3) { flex-shrink: 0; padding: 10px 0; background-color: #fff; border-top: 1px solid #e0e0e0; }
.pgs.cl { margin-bottom: 0 !important; }
.tl { width: 100% !important; max-width: none !important; padding: 0 20px !important; box-sizing: border-box !important; }
#threadlist { width: 100% !important; max-width: none !important; }
#threadlist > ul { width: 100% !important; max-width: none !important; padding: 0 !important; margin: 0 !important; }
.pbw { width: 100% !important; max-width: none !important; box-sizing: border-box !important; margin: 25px 0 !important; }
`,document.head.appendChild(e)}static createRichPostCard(e,t,n,i,a){h.inject(),x.createUnifiedInfoCard(e,t,n,i,a)}}class P{static MIN_POSTS_FOR_TRIGGER=5;static async processSearchContainer(e,t=!1){return await this.displaySearchPreviews(e,t),e.querySelectorAll(".pbw").length}static async displaySearchPreviews(e,t=!1){const n=e.querySelectorAll(".xs3 a"),i=Array.from(n).filter(r=>{const c=r.closest(".pbw");return r.href&&r.href.includes("thread")&&c&&!c.classList.contains("hidden-transparent")}),a=new C(f.get("concurrencyLimit")),s=[],o=i.map(r=>a.addTask(async()=>{try{const c=r.href,l=r.closest(".pbw");if(!l||l.querySelector(".searchImagePreview")||l.querySelector('[id*="imagePreview"]')||l.dataset.previewProcessed==="true")return;l.dataset.previewProcessed="true";const p=t&&i.indexOf(r)<5,u=await v(c,p?"high":"normal");if(!u){s.push({pbwContainer:l,link:r,hasContent:!1,processed:!1,isHidden:this.isHiddenPost(l)});return}const{images:g,links:y}=u,w=g.slice(0,f.get("maxPreviewImages"));if(!(w.length>0||b.hasAnyContent(y))){s.push({pbwContainer:l,link:r,hasContent:!1,processed:!1,isHidden:this.isHiddenPost(l)});return}this.createRichPostCard(l,r,w,y,c),s.push({pbwContainer:l,link:r,hasContent:!0,processed:!0,isHidden:!1})}catch(c){m.error("处理失败:",c);const l=r.closest(".pbw");l&&(l.dataset.previewProcessed="false",s.push({pbwContainer:l,link:r,hasContent:!1,processed:!1,isHidden:this.isHiddenPost(l)}))}}));await Promise.all(o),this.handleInvalidAndHiddenPosts(s)}static createRichPostCard(e,t,n,i,a){F.createRichPostCard(e,t,n,i,a)}static handleInvalidAndHiddenPosts(e){let t=0;e.filter(n=>!n.hasContent&&!n.processed).forEach(n=>{n.isHidden&&(n.pbwContainer.remove(),t++)}),t>0&&m.summary("移除隐藏贴",{隐藏贴:t})}static isHiddenPost(e){const t=e.textContent||"",n=["该主题需要回复才能浏览","内容隐藏需要,请点击进去查看","隐藏内容","此帖被隐藏","权限不足","积分不足","回复可见","购买主题","付费内容","需要权限","您无权访问","内容隐藏需要"].some(o=>t.includes(o)),i=!!(e.querySelector(".locked")||e.querySelector(".permission-denied")||e.querySelector(".reply-to-view")),a=e.querySelector(".xs3 a")?.textContent||"",s=a.includes("隐藏")||a.includes("权限")||a.includes("回复可见")||a.includes("积分不足");return n||i||s}static reprocessExistingPosts(){const e=document.querySelectorAll("#threadlist .pbw");let t=0;e.forEach(n=>{this.isHiddenPost(n)&&(n.remove(),t++)}),t>0&&m.summary("移除隐藏贴",{隐藏贴:t})}static async showCachedContent(e){let t=0;for(const n of e){const i=n.href,a=n.closest(".pbw");if(!a||a.dataset.previewProcessed==="true")continue;const{previewCache:s}=await Promise.resolve().then(()=>U);if(s.has(i)){const o=s.get(i);if(o){a.dataset.previewProcessed="true";const{images:r,links:c}=o,l=r.slice(0,f.get("maxPreviewImages"));(l.length>0||b.hasAnyContent(c))&&(this.createRichPostCard(a,n,l,c,i),t++)}}}t>0&&m.summary("缓存显示",{立即显示:t})}static async loadRemainingContent(e){if(e.length===0)return;const t=new C(f.get("concurrencyLimit")),n=e.map(i=>t.addTask(async()=>{const a=i.href,s=i.closest(".pbw");if(!s||s.dataset.previewProcessed==="true")return;s.dataset.previewProcessed="true";const o=await v(a,"normal");if(o){const{images:r,links:c}=o,l=r.slice(0,f.get("maxPreviewImages"));(l.length>0||b.hasAnyContent(c))&&this.createRichPostCard(s,i,l,c,a)}}));await Promise.allSettled(n),m.summary("后续加载",{加载完成:e.length})}}class S{static scrollHandler=null;static isLoading=!1;static nextPageUrl="";static contentObserver=null;static MIN_VISIBLE_POSTS=8;static MIN_CONTENT_HEIGHT_RATIO=1.8;static contentProcessor=null;static setContentProcessor(e){this.contentProcessor=e}static initializePagination(){const e=document.querySelector(".pg");e?.querySelector("a.nxt")&&(this.nextPageUrl=e.querySelector("a.nxt").href);const t=document.createElement("div");t.id="search-loading-indicator",t.style.cssText="text-align: center; padding: 20px; display: none;",document.getElementById("sticky-scroll-container")?.appendChild(t)}static enableInfiniteScroll(){if(this.scrollHandler)return;const e=document.getElementById("sticky-scroll-container");e&&(this.scrollHandler=R(()=>{if(this.isLoading||!this.nextPageUrl)return;const t=this.getVisiblePostsCount()<this.MIN_VISIBLE_POSTS?e.clientHeight*2:e.clientHeight*.8;e.scrollTop+e.clientHeight>=e.scrollHeight-t&&this.loadNext()},150),e.addEventListener("scroll",this.scrollHandler,{passive:!0}),this.startContentMonitoring(),this.waitForImages(e).then(()=>{this.checkAndEnsureContent()}))}static disableInfiniteScroll(){if(this.scrollHandler){const n=document.getElementById("sticky-scroll-container");n&&n.removeEventListener("scroll",this.scrollHandler),this.scrollHandler=null}this.stopContentMonitoring();const e=document.getElementById("search-loading-indicator");e&&(e.style.display="none");const t=parseInt(document.querySelector(".pg strong")?.textContent||"1",10);if(isNaN(t))window.location.reload();else{const n=new URL(window.location.href);n.searchParams.set("page",t.toString()),window.location.href=n.toString()}}static async loadNext(){if(this.isLoading||!this.nextPageUrl)return;this.isLoading=!0;const e=document.getElementById("search-loading-indicator");e&&(e.style.display="block",e.textContent="正在加载...");try{const n=await(await this.fetchWithTimeout(this.nextPageUrl)).text(),a=new DOMParser().parseFromString(n,"text/html"),s=document.querySelector("#threadlist > ul"),o=a.querySelector("#threadlist > ul");o&&o.children.length>0&&s&&(this.contentProcessor&&this.contentProcessor.processSearchContainer&&await this.contentProcessor.processSearchContainer(o,!1),Array.from(o.children).forEach(p=>{s.appendChild(p)}));const r=a.querySelector(".pg"),c=document.querySelector(".pg");c&&r?c.replaceWith(r):!c&&r&&document.querySelector(".tl")?.appendChild(r);const l=document.querySelector(".pg a.nxt");this.nextPageUrl=l?l.href:""}catch(t){m.error("翻页失败:",t),e&&(e.textContent="加载失败"),this.nextPageUrl=""}finally{this.isLoading=!1,e&&(this.nextPageUrl?e.style.display="none":e.textContent="已加载全部内容")}}static async fetchWithTimeout(e,t={}){const n=new AbortController,i=setTimeout(()=>n.abort(),8e3);try{const a=await fetch(e,{...t,signal:n.signal});return clearTimeout(i),a}catch(a){throw clearTimeout(i),a}}static getVisiblePostsCount(){const e=document.querySelectorAll("#threadlist .pbw");let t=0;return e.forEach(n=>{const i=window.getComputedStyle(n);i.display!=="none"&&i.visibility!=="hidden"&&i.opacity!=="0"&&t++}),t}static startContentMonitoring(){if(this.contentObserver)return;const e=document.getElementById("sticky-scroll-container");e&&(this.contentObserver=new MutationObserver(()=>{setTimeout(()=>{this.checkAndEnsureContent()},100)}),this.contentObserver.observe(e,{childList:!0,subtree:!0}))}static stopContentMonitoring(){this.contentObserver&&(this.contentObserver.disconnect(),this.contentObserver=null)}static async checkAndEnsureContent(){if(this.isLoading||!this.nextPageUrl)return;const e=document.getElementById("sticky-scroll-container");if(!e)return;const t=this.getVisiblePostsCount(),n=e.scrollHeight,i=e.clientHeight,a=n/i;(t<this.MIN_VISIBLE_POSTS||a<this.MIN_CONTENT_HEIGHT_RATIO)&&(m.debug(`内容不足,自动加载更多 - 可见帖子: ${t}, 高度比例: ${a.toFixed(2)}`),await this.loadNext(),setTimeout(()=>{this.checkAndEnsureContent()},500))}static waitForImages(e){const t=Array.from(e.querySelectorAll("img"));if(t.length===0)return Promise.resolve();const n=t.map(i=>new Promise(a=>{i.complete?a():(i.addEventListener("load",()=>a(),{once:!0}),i.addEventListener("error",()=>a(),{once:!0}))}));return Promise.all(n).then(()=>{})}static async ensureSufficientContent(){let e=0;const t=10;for(;this.nextPageUrl&&e<t;){const n=document.getElementById("sticky-scroll-container");if(!n)break;const i=n.scrollHeight,a=n.clientHeight,s=document.querySelectorAll("#threadlist .pbw").length;if(i>a*1.5||s>=5)break;await this.loadNext(),e++,await new Promise(o=>setTimeout(o,300))}}}class K{static init(){F.applyStickyLayout(),j.setupSearchRestore(),this.setupToggle(),setTimeout(()=>{this.setupInitialContent()},0)}static async setupInitialContent(){const e=document.querySelector("#threadlist > ul");e&&(S.initializePagination(),S.setContentProcessor(P),P.reprocessExistingPosts(),await this.processContentInPhases(e))}static async processContentInPhases(e){const t=Array.from(e.querySelectorAll(".xs3 a"));await P.showCachedContent(t.slice(0,8)),setTimeout(async()=>{const n=[...t.slice(0,8).filter(i=>{const a=i.closest(".pbw");return a&&a.dataset.previewProcessed!=="true"}),...t.slice(8)];await P.loadRemainingContent(n),await S.ensureSufficientContent()},100)}static setupToggle(){x.createSearchPageSingleToggle({storageKeyEnabled:"searchPageInfiniteScroll",onEnable:()=>S.enableInfiniteScroll(),onDisable:()=>S.disableInfiniteScroll()})}}window.activeRestoreButton=null,document.readyState==="loading"?document.addEventListener("DOMContentLoaded",B):B();function B(){try{window.location.href.includes("search.php")?K.init():O.init()}catch(d){console.error("[98堂] 执行错误:",d)}}})();