// ==UserScript==
// @name sis001-预览
// @version 1.3.6
// @namespace https://sleazyfork.org/zh-CN/users/1461640-%E6%98%9F%E5%AE%BF%E8%80%81%E9%AD%94
// @author 星宿老魔
// @description sis001第一会所综合社区,帖子图片预览,板块收纳,搜索优化
// @match https://sis001.com/*
// @match https://*.sis001.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=sis001.com
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @run-at document-start
// ==/UserScript==
(function(){"use strict";const e={ACCENT:"#00599F",BORDER_LIGHT:"#e3e6ea",TEXT_PRIMARY:"#2c3e50",TEXT_SECONDARY:"#666",TEXT_LIGHT:"#999",
TEXT_ERROR:"#333"},t={SM:"6px",ROUND:"50%",PILL:"999px"},n={LIGHT:"0 2px 6px rgba(0,0,0,0.08)"},i={select(e){return document.querySelector(e)},
selectAll(e){return document.querySelectorAll(e)},create(e,t={},n={}){const i=document.createElement(e);return Object.entries(t).forEach(([e,t])=>{
i.setAttribute(e,t)}),Object.entries(n).forEach(([e,t])=>{i.style[e]=t}),i},addStyle(e,t){const n=document.createElement("style");return t&&(n.id=t),
n.textContent=e,document.head.appendChild(n),n}};async function a(e,t,n=8){const i=[...e],a=new Set,r=[];async function o(){if(0===i.length)return
;const e=i.shift(),s=t(e).then(e=>{r.push(e)}).finally(()=>{a.delete(s)});return a.add(s),a.size>=n&&await Promise.race(Array.from(a)),o()}
return await o(),await Promise.all(Array.from(a)),r}const r={resolve(e,t){try{return new URL(t,e).href}catch(n){return void 0,t}},isHttp(e){
return/^https?:\/\//i.test(e)}},o={applyButtonStyle(t,options={}){
const{primary:n=!1}=options,i=["display:inline-flex","align-items:center","justify-content:center","height:28px","padding:0 12px","border-radius:6px","font-size:12px","line-height:1","cursor:pointer","user-select:none","white-space:nowrap","box-sizing:border-box"],a=n?`background:${e.ACCENT};color:#fff;border:1px solid ${e.ACCENT}`:`background:#fff;color:${e.TEXT_PRIMARY};border:1px solid ${e.BORDER_LIGHT}`
;t.style.cssText=[...i,a].join(";")},ensureToggleStyles(){if(document.querySelector('style[data-sis-toggle-style="1"]'))return
;const a=`.sis-toggle{display:inline-flex;align-items:center;gap:${t.SM};cursor:pointer;user-select:none;height:28px;padding:0 12px;border:1px solid ${e.BORDER_LIGHT};border-radius:${t.SM};background:#fff;box-shadow:${n.LIGHT};vertical-align:middle;box-sizing:border-box}.sis-toggle .sis-input{position:absolute;opacity:0;width:0;height:0}.sis-toggle .sis-switch{position:relative;width:30px;height:16px;background:#e5e7eb;border-radius:${t.PILL};box-shadow:inset 0 0 0 1px #d1d5db;flex:0 0 30px}.sis-toggle .sis-switch::before{content:"";position:absolute;top:2px;left:2px;width:12px;height:12px;background:#fff;border-radius:${t.ROUND};box-shadow:0 1px 2px rgba(0,0,0,.2)}.sis-toggle .sis-input:checked + .sis-text + .sis-switch{background:${e.ACCENT}}.sis-toggle .sis-input:checked + .sis-text + .sis-switch::before{transform:translateX(14px)}.sis-toggle .sis-text{color:${e.TEXT_ERROR};font-size:12px}`
;i.addStyle(a,"sis-toggle-styles").setAttribute("data-sis-toggle-style","1")}},s={createOverlay(){return i.create("div",{},{position:"fixed",
inset:"0",background:"rgba(0,0,0,0.4)",zIndex:"10001",display:"flex",alignItems:"center",justifyContent:"center"})},createPanel(e="480px"){
return i.create("div",{},{width:e,maxWidth:"92vw",maxHeight:"80vh",overflow:"auto",background:"#fff",borderRadius:"10px",
boxShadow:"0 10px 30px rgba(0,0,0,.2)"})},createHeader(e,t){const n=i.create("div",{},{padding:"12px 16px",borderBottom:"1px solid #e9ecef",
fontWeight:"600",display:"flex",justifyContent:"space-between",alignItems:"center"});n.textContent=e;const a=i.create("button")
;return a.textContent="×",o.applyButtonStyle(a),a.onclick=t,n.appendChild(a),n},createFooter(e,t,n="保存并刷新"){const a=i.create("div",{},{
padding:"12px 16px",borderTop:"1px solid #e9ecef",display:"flex",justifyContent:"flex-end",gap:"10px"}),r=i.create("button");r.textContent="取消",
o.applyButtonStyle(r),r.onclick=e;const s=i.create("button");return s.textContent=n,o.applyButtonStyle(s),s.onclick=t,a.appendChild(r),
a.appendChild(s),a}},c={waitForDOMContentLoaded(){return"loading"===document.readyState?new Promise(e=>{
document.addEventListener("DOMContentLoaded",()=>e(),{once:!0})}):Promise.resolve()},waitForWindowLoad(){
return"complete"!==document.readyState?new Promise(e=>{window.addEventListener("load",()=>e(),{once:!0})}):Promise.resolve()}},l=class{static init(){
this.setupMagnetLinks()}static setupMagnetLinks(){i.select(".t_msgfont")&&i.selectAll(".t_msgfont").forEach(e=>{this.processPost(e)})}
static processPost(e){if(this.processed.has(e))return;const t=/([a-fA-F0-9]{40})/g
;t.test(e.innerHTML)&&(e.innerHTML=e.innerHTML.replace(t,e=>`magnet:?xt=urn:btih:${e}`)),this.processed.add(e)}static refresh(){
this.setupMagnetLinks()}};l.processed=new WeakSet;let d=l;class AdRemover{static init(){this.injectHidingCSS(),this.removeRulesTable(),
this.removePublicMessages(),this.removeStickyTopics(),this.removeImportantTopics(),this.removeAdministrativeThreads(),setTimeout(()=>{
this.removeRulesTable(),this.removePublicMessages(),this.removeStickyTopics(),this.removeImportantTopics(),this.removeAdministrativeThreads()},1e3)}
static injectHidingCSS(){if(i.select('style[data-sis-ad-remover="1"]'))return
;const e='\n /* 立即隐藏本版规则表格 */\n table[summary="Rules and Recommend"] { display: none !important; }\n \n /* 立即隐藏公共消息 */\n .maintable#pmprompt,\n .box#pmprompt { display: none !important; }\n \n /* 立即隐藏固定主题和重要主题区块 */\n thead.separation { display: none !important; }\n tbody[id^="stickthread_"] { display: none !important; }\n \n /* 立即隐藏版务相关帖子(备用CSS) */\n .sis-hide-admin { display: none !important; }\n '
;i.addStyle(e).setAttribute("data-sis-ad-remover","1")}static removeRulesTable(){
const e=document.querySelector('table[summary="Rules and Recommend"]');e&&e.remove()}static removePublicMessages(){
const e=document.querySelector(".maintable#pmprompt");e&&e.remove();const t=document.querySelector(".box#pmprompt");t&&t.remove()}
static removeTopicsByType(e){document.querySelectorAll("thead.separation").forEach(t=>{const n=t.querySelectorAll("font");let i=!1;if(n.forEach(t=>{
e.some(e=>t.textContent?.includes(e))&&(i=!0)}),i){t.remove();let e=t.nextElementSibling
;for(;e&&"TBODY"===e.tagName&&e.id&&e.id.startsWith("stickthread_");){const t=e;e=e.nextElementSibling,t.remove()}}})}static removeStickyTopics(){
this.removeTopicsByType(["固定主題"])}static removeImportantTopics(){this.removeTopicsByType(["重要主題"])}static removeAdministrativeThreads(){
document.querySelectorAll('tbody[id^="stickthread_"], tbody[id^="normalthread_"]').forEach(e=>{
e.querySelectorAll('em a[href*="typeid=528"]').length>0&&(e.classList.add("sis-hide-admin"),setTimeout(()=>{e.remove()},10))})}static refresh(){
this.removeRulesTable(),this.removePublicMessages(),this.removeStickyTopics(),this.removeImportantTopics(),this.removeAdministrativeThreads()}}
class PostLayoutManager{static async transformPostLayout(e,t){if(e.querySelector(".sis-preview-row"))return;const n=e.querySelector("tr");if(!n)return
;let a=0;n.querySelectorAll("th, td").forEach(e=>{const t=parseInt(e.getAttribute("colspan")||"1");a+=t});const r=i.create("tr",{
class:"sis-preview-row"}),o=i.create("td",{colspan:String(a)});o.style.cssText="padding: 15px 20px; background: #fafafa;"
;const s=this.createImageSection();o.appendChild(s),r.appendChild(o),e.appendChild(r),await t(s)}static createImageSection(){
const e=i.create("div",{},{minHeight:"40px"}),t=i.create("div",{},{color:"#999",fontSize:"13px"});return t.textContent="正在加载图片预览...",e.appendChild(t),
e}}class Storage{static get(e,t=null){try{const n=GM_getValue(e);if(null==n)return t;try{return JSON.parse(n)}catch{return n}}catch(n){return void 0,t
}}static set(e,t){try{const n=JSON.stringify(t);return GM_setValue(e,n),!0}catch(n){return void 0,!1}}static delete(e){try{return GM_deleteValue(e),!0
}catch(t){return void 0,!1}}static listKeys(){try{return GM_listValues()}catch(e){return void 0,[]}}static migrateFromLocalStorage(e,t=!0){try{
const n=localStorage.getItem(e);if(null!==n){try{const t=JSON.parse(n);this.set(e,t)}catch{GM_setValue(e,n)}return t&&localStorage.removeItem(e),!0}
return!1}catch(n){return void 0,!1}}}const p={collectNames:"sis_board_collect_names",favoriteNames:"sis_board_favorite_names",
collectionOpen:"sis_board_collection_open",favoriteOpen:"sis_board_favorite_open",searchFavForums:"sis_search_fav_forums",
searchLastSelection:"sis_search_last_selection",searchFavAuto:"sis_search_fav_auto",previewMaxImages:"sis_preview_max_images"},h={
MAX_IMAGES_PER_POST:4};class Config{static getMaxImagesPerPost(){return h.MAX_IMAGES_PER_POST}static getCollectedBoardNames(){try{
const e=Storage.get(p.collectNames,"");if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch(e){return void 0,[]}}
static setCollectedBoardNames(e){try{Storage.set(p.collectNames,JSON.stringify(e||[]))}catch(t){void 0}}static getFavoriteBoardNames(){try{
const e=Storage.get(p.favoriteNames,"");if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?t:[]}catch(e){return void 0,[]}}
static setFavoriteBoardNames(e){try{Storage.set(p.favoriteNames,JSON.stringify(e||[]))}catch(t){void 0}}static getCollectionOpen(){try{
return"1"===(Storage.get(p.collectionOpen,"0")??"0")}catch(e){return void 0,!1}}static setCollectionOpen(e){try{
Storage.set(p.collectionOpen,e?"1":"0")}catch(t){void 0}}static getFavoriteOpen(){try{return"1"===(Storage.get(p.favoriteOpen,"0")??"0")}catch(e){
return void 0,!1}}static setFavoriteOpen(e){try{Storage.set(p.favoriteOpen,e?"1":"0")}catch(t){void 0}}static getSearchFavForums(){try{
const e=Storage.get(p.searchFavForums,"");return e?JSON.parse(e):[]}catch(e){return void 0,[]}}static setSearchFavForums(e){try{
Storage.set(p.searchFavForums,JSON.stringify(e||[]))}catch(t){void 0}}static getSearchFavAuto(){try{
return"1"===(Storage.get(p.searchFavAuto,"0")??"0")}catch(e){return void 0,!1}}static setSearchFavAuto(e){try{Storage.set(p.searchFavAuto,e?"1":"0")
}catch(t){void 0}}static getSearchLastSelection(){try{const e=Storage.get(p.searchLastSelection,"");return e?JSON.parse(e):[]}catch(e){return void 0,
[]}}static setSearchLastSelection(e){try{Storage.set(p.searchLastSelection,JSON.stringify(e||[]))}catch(t){void 0}}}class ImageExtractor{
static extractAndGroupImages(e){const t=e.querySelector(".t_msgfont")||e.querySelector(".postmessage");if(!t)return{images:[],domainGroups:new Map}
;const n=t.cloneNode(!0);this.cleanContentClone(n)
;const i=Array.from(n.querySelectorAll("img")),a=i.filter(e=>this.isValidContentImage(e)),r=this.groupImagesByDomain(a);this.applyImageLimits(r)
;const o=Array.from(r.keys()),s=o[0]||"",c=r.get(s)||[];return this.logExtractionResults(c,i,o),{images:c,domainGroups:r}}static cleanContentClone(e){
e.querySelectorAll(".quote").forEach(e=>e.remove()),e.querySelectorAll(".ad_pip, .ad_thread3_0, .ad_thread4_0").forEach(e=>e.remove()),
e.querySelectorAll(".postratings, .comment_digg").forEach(e=>e.remove())}static isValidContentImage(e){
const t=e.getAttribute("onclick")||"",n=e.getAttribute("onload")||"",i=e.getAttribute("src")||e.src||""
;if(!i||i.length<=10||i.includes("data:"))return!1;if(!/\.(jpg|jpeg|png|gif|webp)(\?|$)/i.test(i))return!1
;if(i.includes("images/green001/")||i.includes("images/attachicons/")||i.includes("images/joinvip.gif")||i.includes("/ad_")||i.includes("advertisement"))return!1
;if(i.includes("images/smilies/")&&this.isSmallImage(e))return!1
;if(i.includes("images/common/")&&(i.match(/\/(she|mengmengda|yang|\d{5}SIS\d+)\.gif$/)||this.isSmallImage(e)))return!1
;if(i.includes("attachments/month_1605/20160525_dcf868ad")&&i.includes(".gif"))return!1;const a=t.includes("zoom(this"),r=n.includes("attachimg(this")
;return a&&r}static groupImagesByDomain(e){const t=new Map;return e.forEach(e=>{const n=this.getImageSource(e),i=this.extractDomain(n)
;t.has(i)||t.set(i,[]),t.get(i).push(e)}),t}static applyImageLimits(e){const t=Config.getMaxImagesPerPost();Array.from(e.keys()).forEach(n=>{
const i=e.get(n)||[];e.set(n,i.slice(0,t))})}static logExtractionResults(e,t,n){e.length>0?void 0:t.length>5&&(void 0,
("localhost"===window.location.hostname||window.location.hostname.includes("dev"))&&t.slice(0,3).forEach((e,t)=>{e.getAttribute("src")||e.src,
e.getAttribute("onclick"),e.getAttribute("onload")}))}static isSmallImage(e){const t=e.getAttribute("width"),n=e.getAttribute("height");if(t||n){
const e=parseInt(t||"0",10),i=parseInt(n||"0",10);if(e>0&&e<=100||i>0&&i<=100)return!0}const i=e.style;if(i.width||i.height){
const e=parseInt(i.width,10),t=parseInt(i.height,10);if(e>0&&e<=100||t>0&&t<=100)return!0}
if(e.naturalWidth>0&&e.naturalHeight>0&&(e.naturalWidth<=100||e.naturalHeight<=100))return!0;const a=e.getAttribute("src")||""
;return[/\/meemo\d{3}\.gif$/i,/\/\w{2,6}\.gif$/i,/\/emoji_\w+\.gif$/i,/\/smiley_\w+\.gif$/i].some(e=>e.test(a))}static extractDomain(e){try{
return new URL(e).hostname}catch{return"unknown"}}static getImageSource(e){return e.getAttribute("src")||e.src||""}}const g=class{static get(e){
const t=this.cache.get(e);return t?Date.now()-t.timestamp>this.maxAge?(this.cache.delete(e),null):t:null}static set(e,t,n){
if(this.cache.size>=this.maxSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}this.cache.set(e,{urls:t,domainGroups:n,
timestamp:Date.now(),extractedCount:t.length})}static cleanup(){const e=Date.now(),t=[];this.cache.forEach((n,i)=>{
e-n.timestamp>this.maxAge&&t.push(i)}),t.forEach(e=>this.cache.delete(e)),t.length>0}static getStats(){return{size:this.cache.size,
maxSize:this.maxSize}}static clear(){this.cache.clear()}};g.cache=new Map,g.maxSize=800,g.maxAge=72e5;let u=g;class ImageLoader{
static async loadImagesForPost(e,t,n,i=0){const a=2,o=u.get(e);if(o&&0===i)return void 0,t.innerHTML="",
0===o.urls.length?(this.showSimpleNoImageMessage(t),void 0):(n&&n(o.urls,o.domainGroups),void 0);try{const i=await fetch(e)
;if(!i.ok)throw new Error(`请求失败,状态码: ${i.status}`);const a=await i.text();if(a.includes("<b>Parse error</b>"))throw new Error("服务器返回PHP解析错误")
;const o=(new DOMParser).parseFromString(a,"text/html"),{images:s,domainGroups:c}=ImageExtractor.extractAndGroupImages(o);if(t.innerHTML="",
0===s.length)return this.showSimpleNoImageMessage(t),u.set(e,[],new Map),void 0;const l=s.map(t=>r.resolve(e,ImageExtractor.getImageSource(t)))
;return u.set(e,l,c),n&&n(l,c),void 0}catch(s){const r=s instanceof Error?s.message:"未知错误";0===i||r.includes("Parse error")||r.includes("500"),0
;const o=i<a,c=0===i?"重试":`重试 (${i}/${a})`;return this.showStaticFailureMessage(t,r.includes("403")||r.includes("权限")?"访问受限":"加载失败",o?()=>{
setTimeout(()=>{this.loadImagesForPost(e,t,n,i+1)},Math.min(1e3+1e3*i,3e3))}:void 0,c),void 0}}static showStaticFailureMessage(t,n,a,r="重试"){
t.innerHTML="",
t.style.cssText="\n padding: 8px 20px;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n height: auto;\n min-height: 30px;\n max-height: 30px;\n gap: 10px;\n "
;const o=i.create("div",{},{color:e.TEXT_LIGHT,fontSize:"13px",fontStyle:"italic",lineHeight:"1.2"});if(o.textContent=n,t.appendChild(o),a){
const n=i.create("button")
;n.textContent=r,n.style.cssText=`\n padding: 2px 8px;\n font-size: 11px;\n margin-left: 8px;\n cursor: pointer;\n border: 1px solid ${e.TEXT_LIGHT};\n background: transparent;\n border-radius: 3px;\n color: ${e.TEXT_LIGHT};\n `,
n.onclick=e=>{e.stopPropagation(),a()},t.appendChild(n)}}static showSimpleNoImageMessage(t){t.innerHTML="",
t.style.cssText="\n padding: 8px 20px;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n height: auto;\n min-height: 30px;\n max-height: 30px;\n "
;const n=i.create("div",{},{color:e.TEXT_LIGHT,fontSize:"13px",fontStyle:"italic",textAlign:"center",lineHeight:"1.2"});n.textContent="帖子内无图片内容",
t.appendChild(n)}}const m=class{static init(){this.overlay||(this.overlay=document.createElement("div"),
this.overlay.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.95);\n z-index: 999999;\n display: none;\n align-items: center;\n justify-content: center;\n ",
this.img=document.createElement("img"),
this.img.style.cssText="\n max-width: 85%;\n max-height: 85%;\n object-fit: contain;\n border-radius: 4px;\n ",
this.counter=document.createElement("div"),
this.counter.style.cssText="\n position: absolute;\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n color: white;\n background: rgba(0, 0, 0, 0.6);\n padding: 8px 16px;\n border-radius: 20px;\n font-size: 14px;\n ",
this.prevBtn=this.createNavButton("‹","left"),this.nextBtn=this.createNavButton("›","right"),this.overlay.appendChild(this.img),
this.overlay.appendChild(this.counter),this.overlay.appendChild(this.prevBtn),this.overlay.appendChild(this.nextBtn),
document.body.appendChild(this.overlay),this.setupEvents())}static createNavButton(e,t){const n=document.createElement("button")
;return n.innerHTML="‹"===e?'<svg viewBox="0 0 24 24" fill="white" width="30" height="30"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>':'<svg viewBox="0 0 24 24" fill="white" width="30" height="30"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>',
n.style.cssText=`\n position: fixed;\n ${t}: 16px;\n top: 50%;\n transform: translateY(-50%);\n width: 40px;\n height: 40px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 50%;\n border: none;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n cursor: pointer;\n user-select: none;\n z-index: 10002;\n `,
n}static setupEvents(){this.overlay.onclick=e=>{e.target===this.overlay&&this.close()},this.prevBtn.onclick=e=>{e.stopPropagation(),this.prev()},
this.nextBtn.onclick=e=>{e.stopPropagation(),this.next()},document.addEventListener("keydown",e=>{
"flex"===this.overlay?.style.display&&("Escape"===e.key?this.close():"ArrowLeft"===e.key?this.prev():"ArrowRight"===e.key&&this.next())})}
static show(e,t=0){this.init(),this.images=e,this.currentIndex=t,this.updateImage(),this.overlay.style.display="flex"}static close(){
this.overlay&&(this.overlay.style.display="none")}static prev(){this.currentIndex=(this.currentIndex-1+this.images.length)%this.images.length,
this.updateImage()}static next(){this.currentIndex=(this.currentIndex+1)%this.images.length,this.updateImage()}static updateImage(){
const e=this.images[this.currentIndex];this.img.style.display="none",this.img.src="",
this.counter.textContent=`${this.currentIndex+1} / ${this.images.length}`,this.images.length<=1?(this.prevBtn.style.display="none",
this.nextBtn.style.display="none",this.counter.style.display="none"):(this.prevBtn.style.display="flex",this.nextBtn.style.display="flex",
this.counter.style.display="block"),this.img.onload=()=>{this.img.style.display="block"},this.img.onerror=()=>{this.img.alt="图片加载失败"},this.img.src=e}}
;m.overlay=null,m.img=null,m.counter=null,m.prevBtn=null,m.nextBtn=null,m.images=[],m.currentIndex=0;let f=m;class ImageRenderer{
static renderImages(e,t,n,i,a=0){e.innerHTML="";const o=Array.from(i.keys());if(0===o.length||0===t.length)return this.showGlobalFailure(e),void 0
;if(a>=o.length)return void 0,this.showGlobalFailure(e),void 0;const s=o[a],c=i.get(s)||[];if(0===c.length)return this.showGlobalFailure(e),void 0
;const l=c.map(e=>r.resolve(n,ImageExtractor.getImageSource(e)));void 0;const d=document.createElement("div")
;d.style.cssText="\n display: flex !important;\n gap: 12px !important;\n width: 100% !important;\n ";let p=0,h=0;const g=l.length
;l.forEach((s,c)=>{const l=document.createElement("div")
;l.style.cssText="\n flex: 1 !important;\n min-width: 0 !important;\n height: 200px !important;\n background: #f5f5f5 !important;\n border-radius: 4px !important;\n overflow: hidden !important;\n cursor: pointer !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n "
;const u=document.createElement("img")
;u.src=s,u.style.cssText="\n max-width: 100% !important;\n max-height: 100% !important;\n width: auto !important;\n height: auto !important;\n object-fit: contain !important;\n display: block !important;\n ",
u.onload=()=>{h++},u.onerror=()=>{p++,p+h===g&&(p>g/2&&a<o.length-1?(void 0,setTimeout(()=>{this.renderImages(e,t,n,i,a+1)
},500)):p===g&&a<o.length-1&&(void 0,this.renderImages(e,t,n,i,a+1)))},l.onclick=e=>{e.preventDefault(),e.stopPropagation()
;const i=t.map(e=>r.resolve(n||location.href,e));f.show(i,c)},l.appendChild(u),d.appendChild(l)}),e.appendChild(d)}static showGlobalFailure(t){
t.innerHTML="",
t.style.cssText="\n padding: 8px 20px;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n height: auto;\n min-height: 30px;\n max-height: 30px;\n "
;const n=i.create("div",{},{fontSize:"12px",color:e.TEXT_SECONDARY,textAlign:"center",fontStyle:"italic"});n.textContent="帖子内可能无图",t.appendChild(n)}}
class ImagePreview{static async init(){await this.displayThreadImages()}static async displayThreadImages(){
if(i.select(".postmessage")||i.select("#postlist")||i.select(".plhin")||i.select(".t_msgfont"))return
;const e=window.location.href.includes("/search.php"),t=window.location.href.includes("/tag.php");let n=[];if(e||t){const e=i.selectAll("tbody")
;n=Array.from(e).filter(e=>{const t=e.querySelector('a[href*="thread-"], a[href*="viewthread.php"]'),n=e.querySelector(".icon");return t&&n})}else{
const e=i.selectAll('tbody[id^="normalthread_"]');n=Array.from(e)}
const r=n.filter(e=>(!e.id||!e.id.startsWith("stickthread_"))&&(!e.querySelector(".new-post-layout")&&!!e.querySelector('a[href*="thread-"], a[href*="viewthread.php"]')))
;await a(r,async e=>{const t=e.querySelector('a[href*="thread-"], a[href*="viewthread.php"]');if(!t)return;const n=t.href
;let i=t.textContent?.trim()||"";if(!i){const t=e.querySelector('span[id^="thread_"]');t&&(i=t.textContent?.trim()||"")}
await PostLayoutManager.transformPostLayout(e,async e=>{await ImageLoader.loadImagesForPost(n,e,(t,i)=>{ImageRenderer.renderImages(e,t,n,i)})})},15)}}
class BoardManager{static init(){this.normalizeExclusiveLists(),this.setupBoardCollectionCollapse(),this.setupBoardFavoriteSection()}
static normalizeExclusiveLists(){const e=new Set(Config.getFavoriteBoardNames()),t=new Set(Config.getCollectedBoardNames());let n=!1;e.forEach(e=>{
t.has(e)&&(t.delete(e),n=!0)}),n&&Config.setCollectedBoardNames(Array.from(t))}static findBoardElementsMap(){const e=new Map
;return i.selectAll("div.mainbox.forumlist").forEach(t=>{const n=t.querySelector("h3 > a"),i=n?.textContent?.trim()||"";i&&!e.has(i)&&e.set(i,t)}),e}
static moveBoardsToContainer(e,t){const n=this.findBoardElementsMap(),i=[];return e.forEach(e=>{const a=n.get(e);a&&(t.appendChild(a),i.push(e))}),i}
static setupBoardCollectionCollapse(){this.setupBoardSection({containerId:"board-collection-container",title:"板块收纳区",
getBoardNames:()=>Config.getCollectedBoardNames(),getOpenState:()=>Config.getCollectionOpen(),setOpenState:e=>Config.setCollectionOpen(e),
onSettings:()=>this.openBoardCollectSettings(),insertMethod:e=>this.insertContainer(e),emptyMessage:'未选择任何板块,可点击右侧"设置"进行选择。'})}
static setupBoardFavoriteSection(){this.setupBoardSection({containerId:"board-favorite-container",title:"板块收藏区",
getBoardNames:()=>Config.getFavoriteBoardNames(),getOpenState:()=>Config.getFavoriteOpen(),setOpenState:e=>Config.setFavoriteOpen(e),
onSettings:()=>this.openBoardFavoriteSettings(),insertMethod:e=>this.insertFavoriteContainer(e),emptyMessage:'未选择任何收藏板块,可点击右侧"设置"进行选择。'})}
static setupBoardSection(config){if(i.select(`#${config.containerId}`))return
;const e=new Set(config.getBoardNames()),t=Array.from(i.selectAll("div.mainbox.forumlist"));if(0===t.length)return;const n=t.filter(t=>{
const n=t.querySelector("h3 > a"),i=n?.textContent?.trim()||"";return i&&e.has(i)
}),a=this.createBoardContainer(config.containerId,config.title,n.length),{content:r}=this.setupContainerElements(a,{isOpen:config.getOpenState(),
onToggle:config.setOpenState,onSettings:config.onSettings,title:config.title,count:n.length});if(config.insertMethod(a),
0===n.length)this.showEmptyMessage(r,config.emptyMessage);else{const e=n.map(e=>{const t=e.querySelector("h3 > a");return t?.textContent?.trim()||""})
;this.moveBoardsToContainer(e,r)}}static createBoardContainer(e,t,n){return i.create("div",{id:e},{margin:"12px 0",border:"1px solid #e3e6ea",
borderRadius:"10px",boxShadow:"0 3px 12px rgba(0,0,0,0.08)",overflow:"hidden",background:"#fff"})}static setupContainerElements(e,options){
const t=i.create("div",{},{padding:"10px 14px",background:options.isOpen?"#f0f0f0":"linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%)",
border:options.isOpen?"2px solid #d0d0d0":"none",borderBottom:"1px solid #e9ecef",cursor:"pointer",userSelect:"none",display:"flex",
alignItems:"center",justifyContent:"space-between"}),n=i.create("span",{},{fontWeight:"600",color:"#2c3e50",fontSize:"14px"})
;n.textContent=`${options.title}(共 ${options.count} 个)`;const a=i.create("span",{},{fontSize:"12px",color:"#666"})
;a.textContent=options.isOpen?"[点击收起]":"[点击展开]";const r=i.create("button");r.textContent="设置",r.title="选择需要管理的板块",o.applyButtonStyle(r),
r.addEventListener("click",e=>{e.stopPropagation(),options.onSettings()});const s=i.create("div",{},{display:"flex",alignItems:"center",gap:"10px"})
;s.appendChild(a),s.appendChild(r),t.appendChild(n),t.appendChild(s);const c=i.create("div",{},{padding:"10px",background:"#fafafa",
border:"2px solid #d0d0d0",borderTop:"none",display:options.isOpen?"":"none"});return t.addEventListener("click",()=>{const e="none"===c.style.display
;c.style.display=e?"":"none",a.textContent=e?"[点击收起]":"[点击展开]",t.style.background=e?"#f0f0f0":"linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%)",
t.style.border=e?"2px solid #d0d0d0":"none",t.style.borderBottom="1px solid #e9ecef",options.onToggle(e)}),e.appendChild(t),e.appendChild(c),{
header:t,content:c,toggleHint:a}}static insertContainer(e){
const t=i.select('table.portalbox[summary="HeadBox"]')||i.select("#hottags")?.closest("table")||i.select("#hottags");if(t?.parentNode){
const n=t.parentNode;t.nextSibling?n.insertBefore(e,t.nextSibling):n.appendChild(e)}else document.body.appendChild(e)}
static insertFavoriteContainer(e){const t=i.select("#board-collection-container");if(t?.parentNode){const n=t.parentNode
;t.nextSibling?n.insertBefore(e,t.nextSibling):n.appendChild(e)}else this.insertContainer(e)}static showEmptyMessage(e,t){const n=i.create("div",{},{
color:"#666",fontSize:"12px"});n.textContent=t,e.appendChild(n)}static openBoardCollectSettings(){const e=this.getAllBoardNames()
;this.openBoardSettings(e,Config.getCollectedBoardNames(),"板块收纳设置","勾选需要收纳到顶部的板块:",e=>{const t=new Set(Config.getFavoriteBoardNames())
;e.forEach(e=>t.delete(e)),Config.setFavoriteBoardNames(Array.from(t)),Config.setCollectedBoardNames(e),location.reload()})}
static openBoardFavoriteSettings(){const e=this.getAllBoardNames()
;this.openBoardSettings(e,Config.getFavoriteBoardNames(),"板块收藏设置",'勾选需要加入"板块收藏区"的板块:',e=>{const t=new Set(Config.getCollectedBoardNames())
;e.forEach(e=>t.delete(e)),Config.setCollectedBoardNames(Array.from(t)),Config.setFavoriteBoardNames(e),location.reload()})}static getAllBoardNames(){
const e=Array.from(i.selectAll("div.mainbox.forumlist > h3 > a")).map(e=>e.textContent?.trim()||"").filter(Boolean);return Array.from(new Set(e))}
static openBoardSettings(e,t,n,a,r){const o=s.createOverlay(),c=s.createPanel("520px"),l=s.createHeader(n,()=>o.remove()),d=i.create("div",{},{
padding:"12px 16px"}),p=i.create("div",{},{color:"#666",marginBottom:"8px"});p.textContent=a,d.appendChild(p);const h=i.create("div",{},{
display:"grid",gridTemplateColumns:"1fr 1fr",gap:"6px"}),g=new Set(t);e.forEach(e=>{const t=i.create("label",{},{display:"flex",alignItems:"center",
gap:"6px",padding:"6px",border:"1px solid #eee",borderRadius:"6px"}),n=i.create("input",{type:"checkbox"});n.checked=g.has(e),n.onchange=()=>{
n.checked?g.add(e):g.delete(e)};const a=i.create("span");a.textContent=e,t.appendChild(n),t.appendChild(a),h.appendChild(t)}),d.appendChild(h)
;const u=s.createFooter(()=>o.remove(),()=>r(Array.from(g)));c.appendChild(l),c.appendChild(d),c.appendChild(u),o.appendChild(c),
document.body.appendChild(o)}}class SearchOptimizer{static init(){this.setupSearchFavorites()}static setupSearchFavorites(){
if(!/\/search\.php(\?|$)/.test(location.pathname+location.search))return;const e=i.select("#srchfid")
;e&&"SELECT"===e.tagName&&e.multiple&&(this.createSearchTools(e),this.setupTopGrouping(e),this.setupAutoRemember(e))}static createSearchTools(e){
const t=i.create("div",{},{margin:"6px 0",display:"flex",gap:"12px",alignItems:"center"}),n=i.create("button",{type:"button"},{height:"30px"})
;n.textContent="置顶设置",o.applyButtonStyle(n),n.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),this.openSearchFavSettings(e)}),
o.ensureToggleStyles();const{switchWrap:a}=this.createToggleSwitch();t.appendChild(n),t.appendChild(a),e.parentNode?.insertBefore(t,e)}
static createToggleSwitch(){const e=i.create("label",{class:"sis-toggle"}),t=i.create("input",{type:"checkbox",class:"sis-input"})
;t.checked=Config.getSearchFavAuto();const n=i.create("span",{class:"sis-text"});n.textContent="多选记忆";const a=i.create("span",{class:"sis-switch"})
;return e.appendChild(t),e.appendChild(n),e.appendChild(a),t.addEventListener("change",()=>{if(Config.setSearchFavAuto(t.checked),t.checked){
const e=i.select("#srchfid");if(e){const t=Array.from(e.selectedOptions).map(e=>e.value).filter(Boolean);t.length>0&&Config.setSearchLastSelection(t)}
}}),{switchWrap:e,switchInput:t}}static setupTopGrouping(e){const t=Config.getSearchFavForums();if(0===t.length)return;const n=i.create("optgroup",{
label:"常用置顶"});e.insertBefore(n,e.firstChild);const options=Array.from(e.querySelectorAll("option"));t.forEach(e=>{
const t=options.find(t=>t.value===e);t&&n.appendChild(t)})}static setupAutoRemember(e){if(!Config.getSearchFavAuto())return
;const t=Config.getSearchLastSelection();t.length>0&&Array.from(e.options).forEach(e=>{e.selected=t.includes(e.value)}),
e.addEventListener("change",()=>{const t=Array.from(e.selectedOptions).map(e=>e.value).filter(Boolean);Config.setSearchLastSelection(t)})}
static openSearchFavSettings(e){
const t=Array.from(e.querySelectorAll("option")).filter(e=>e.value),n=s.createOverlay(),i=s.createPanel("1100px"),a=s.createHeader("置顶设置",()=>n.remove()),{body:r,favSet:o}=this.createPanelBody(e,t),c=s.createFooter(()=>n.remove(),()=>{
Config.setSearchFavForums(Array.from(o)),location.reload()});i.appendChild(a),i.appendChild(r),i.appendChild(c),n.appendChild(i),
document.body.appendChild(n)}static createPanelBody(e,t){const n=i.create("div",{},{padding:"12px 16px",display:"grid",
gridTemplateColumns:"repeat(auto-fit,minmax(260px,1fr))",gap:"12px"}),a=new Set(Config.getSearchFavForums())
;return this.organizeOptions(e,t).forEach(e=>{const t=this.createGroupCard(e,a);n.appendChild(t)}),{body:n,favSet:a}}static organizeOptions(e,t){
const n=[];Array.from(e.querySelectorAll("optgroup")).forEach(e=>{const options=Array.from(e.querySelectorAll("option")).filter(e=>e.value)
;options.length>0&&n.push({label:e.label||"分组",options:options})})
;const i=Array.from(e.children).filter(e=>"OPTION"===e.tagName&&e.value&&"all"!==e.value);return i.length>0&&n.unshift({label:"其他",options:i}),n}
static createGroupCard(e,t){const n=i.create("div",{},{border:"1px solid #e9ecef",borderRadius:"8px",overflow:"hidden",background:"#fff"
}),a=i.create("div",{},{padding:"8px 10px",background:"#f8f9fa",borderBottom:"1px solid #e9ecef",fontWeight:"600",color:"#2c3e50",fontSize:"12px"})
;a.textContent=e.label;const r=i.create("div",{},{padding:"8px 10px",display:"flex",flexDirection:"column",gap:"6px"});return e.options.forEach(e=>{
const n=i.create("label",{},{display:"flex",alignItems:"center",gap:"6px",padding:"6px",border:"1px solid #eee",borderRadius:"6px"
}),a=i.create("input",{type:"checkbox"});a.checked=t.has(e.value),a.onchange=()=>{a.checked?t.add(e.value):t.delete(e.value)};const o=i.create("span")
;o.textContent=e.textContent?.trim()||"",n.appendChild(a),n.appendChild(o),r.appendChild(n)}),n.appendChild(a),n.appendChild(r),n}}async function y(){
try{x(),AdRemover.init(),"loading"===document.readyState&&await c.waitForDOMContentLoaded(),d.init(),await c.waitForWindowLoad(),
await ImagePreview.init(),BoardManager.init(),SearchOptimizer.init(),setInterval(()=>{u.cleanup()},3e5)}catch(e){void 0}}function x(){
const e=document.querySelectorAll("a");for(let t=0;t<e.length;t++){const n=e[t];if(n.textContent&&n.textContent.includes("电脑版")){
window.location.href=n.href;break}}}y()})();