XT 2.1.1: fix error when date format locale not set

This commit is contained in:
Tuxedo Takodachi 2023-07-16 10:55:01 +02:00
parent 52a847bfa5
commit 3f34c5fb75
9 changed files with 23069 additions and 23061 deletions

View File

@ -3,6 +3,11 @@
4chan XT uses a different user script namespace, so to migrate you need to export settings from 4chan X, and import them
in XT.
### XT v2.1.1 (2023-07-16)
- Time formatting now falls back to browser locale instead of giving an error when the locale is not set.
- Update notification link now links to the changelog on the right branch on github.
### XT v2.1.0 (2023-06-24)
- Limited support for audio posts: they work in threads but not yet in the gallery. Might add if there's demand.

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,11 @@
// ==UserScript==
// @name 4chan XT
// @version XT 2.0.1
// @version XT 2.1.1
// @minGMVer 1.14
// @minFFVer 74
// @namespace 4chan-XT
// @description 4chan XT is a script that adds various features to anonymous imageboards.
// @license MIT; https://github.com/TuxedoTako/4chan-xt/blob/master/LICENSE
// @license MIT; https://github.com/TuxedoTako/4chan-xt/blob/project-XT/LICENSE
// @include http://boards.4chan.org/*
// @include https://boards.4chan.org/*
// @include http://sys.4chan.org/*
@ -184,10 +184,10 @@
*
* Icons used to identify various websites are property of the respective websites.
*/
!function(){"use strict";var e={name:"4chan XT",path:"4chan-XT",fork:"TuxedoTako",page:"https://github.com/TuxedoTako/4chan-xt",downloads:"https://github.com/TuxedoTako/4chan-xt/releases",oldVersions:"https://raw.githubusercontent.com/ccd0/4chan-x/",faq:"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions",captchaFAQ:"https://github.com/ccd0/4chan-x/wiki/Captcha-FAQ",cssGuide:"https://github.com/ccd0/4chan-x/wiki/Styling-Guide",license:"https://github.com/TuxedoTako/4chan-xt/blob/master/LICENSE",changelog:"https://github.com/TuxedoTako/4chan-xt/blob/master/CHANGELOG.md",issues:"https://github.com/TuxedoTako/4chan-xt/issues",newIssue:"https://github.com/TuxedoTako/4chan-xt/issues",newIssueMaxLength:8181,alternatives:"https://www.4chan-x.net/4chan_alternatives.html",appid:"lacclbnghgdicfifcamcmcnilckjamag",appidGecko:"4chan-x@4chan-x.net",chromeStoreID:"ohnjgmpcibpbafdlkimncjhflgedgpam",recaptchaKey:"6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc",distBranch:"gh-pages",
!function(){"use strict";var e={name:"4chan XT",path:"4chan-XT",fork:"TuxedoTako",page:"https://github.com/TuxedoTako/4chan-xt",downloads:"https://github.com/TuxedoTako/4chan-xt/releases",oldVersions:"https://raw.githubusercontent.com/ccd0/4chan-x/",faq:"https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions",captchaFAQ:"https://github.com/ccd0/4chan-x/wiki/Captcha-FAQ",cssGuide:"https://github.com/ccd0/4chan-x/wiki/Styling-Guide",license:"https://github.com/TuxedoTako/4chan-xt/blob/project-XT/LICENSE",changelog:"https://github.com/TuxedoTako/4chan-xt/blob/project-XT/CHANGELOG.md",issues:"https://github.com/TuxedoTako/4chan-xt/issues",newIssue:"https://github.com/TuxedoTako/4chan-xt/issues",newIssueMaxLength:8181,alternatives:"https://www.4chan-x.net/4chan_alternatives.html",appid:"lacclbnghgdicfifcamcmcnilckjamag",appidGecko:"4chan-x@4chan-x.net",chromeStoreID:"ohnjgmpcibpbafdlkimncjhflgedgpam",recaptchaKey:"6Ldp2bsSAAAAAAJ5uyx_lx34lJeEpTLVkP5k04qc",distBranch:"gh-pages",
includes_only:["*://boards.4chan.org/*","*://sys.4chan.org/*","*://www.4chan.org/*","*://boards.4channel.org/*","*://sys.4channel.org/*","*://www.4channel.org/*","*://i.4cdn.org/*","*://is.4chan.org/*","*://is2.4chan.org/*","*://is.4channel.org/*","*://is2.4channel.org/*"],matches_only:["*://*.4chan.org/*","*://*.4channel.org/*","*://*.4cdn.org/*"],
matches:["https://erischan.org/*","https://www.erischan.org/*","https://fufufu.moe/*","https://gnfos.com/*","https://himasugi.blog/*","https://www.himasugi.blog/*","https://kakashinenpo.com/*","https://www.kakashinenpo.com/*","https://kissu.moe/*","https://www.kissu.moe/*","https://lainchan.org/*","https://www.lainchan.org/*","https://merorin.com/*","https://ota-ch.com/*","https://www.ota-ch.com/*","https://ponyville.us/*","https://www.ponyville.us/*","https://smuglo.li/*","https://notso.smuglo.li/*","https://smugloli.net/*","https://smug.nepu.moe/*","https://sportschan.org/*","https://www.sportschan.org/*","https://sushigirl.us/*","https://www.sushigirl.us/*","https://tvch.moe/*"],matches_extra:[],exclude_matches:["*://www.4chan.org/advertise","*://www.4chan.org/advertise?*","*://www.4chan.org/donate","*://www.4chan.org/donate?*","*://www.4channel.org/advertise","*://www.4channel.org/advertise?*","*://www.4channel.org/donate","*://www.4channel.org/donate?*"],
grants:["GM_getValue","GM_setValue","GM_deleteValue","GM_listValues","GM_addValueChangeListener","GM_openInTab","GM_xmlhttpRequest","GM.getValue","GM.setValue","GM.deleteValue","GM.listValues","GM.openInTab","GM.xmlHttpRequest"],min:{chrome:"80",firefox:"74",greasemonkey:"1.14"}};const t=Object.create(null),n={VERSION:"XT 2.0.1",NAMESPACE:e.name,sites:Object.create(null),boards:Object.create(null)},o=function(){const e={"&":"&amp;","'":"&#039;",'"':"&quot;","<":"&lt;",">":"&gt;"},t=/[&"'<>]/g,n=function(t){return e[t]},o=function(e){return e.toString().replace(t,n)};return o.cat=function(e){let t="";for(let n=0;n<e.length;n++)t+=e[n].innerHTML;return t},o}(),a=document,i=a.documentElement,r=console,s=function(){return i};class l{static initClass(){this.Post=new l("Post"),this.Thread=new l("Thread"),this.CatalogThread=new l("Catalog Thread"),this.CatalogThreadNative=new l("Catalog Thread")}constructor(e){this.type=e,this.keys=[]}push({name:e,cb:t}){return this[e]||this.keys.push(e),
grants:["GM_getValue","GM_setValue","GM_deleteValue","GM_listValues","GM_addValueChangeListener","GM_openInTab","GM_xmlhttpRequest","GM.getValue","GM.setValue","GM.deleteValue","GM.listValues","GM.openInTab","GM.xmlHttpRequest"],min:{chrome:"80",firefox:"74",greasemonkey:"1.14"}};const t=Object.create(null),n={VERSION:"XT 2.1.1",NAMESPACE:e.name,sites:Object.create(null),boards:Object.create(null)},o=function(){const e={"&":"&amp;","'":"&#039;",'"':"&quot;","<":"&lt;",">":"&gt;"},t=/[&"'<>]/g,n=function(t){return e[t]},o=function(e){return e.toString().replace(t,n)};return o.cat=function(e){let t="";for(let n=0;n<e.length;n++)t+=e[n].innerHTML;return t},o}(),a=document,i=a.documentElement,r=console,s=function(){return i};class l{static initClass(){this.Post=new l("Post"),this.Thread=new l("Thread"),this.CatalogThread=new l("Catalog Thread"),this.CatalogThreadNative=new l("Catalog Thread")}constructor(e){this.type=e,this.keys=[]}push({name:e,cb:t}){return this[e]||this.keys.push(e),
this[e]=t}execute(e,t=this.keys,n=!1){let o;if(!e.callbacksExecuted||n){for(var a of(e.callbacksExecuted=!0,t))try{this[a]?.call(e)}catch(t){o||(o=[]),o.push({message:['"',a,'" crashed on node ',this.type," No.",e.ID," (",e.board,")."].join(""),error:t,html:e.nodes?.root?.outerHTML})}return o?Ot.handleErrors(o):void 0}}}l.initClass();const c={main:{Miscellaneous:{"Redirect to HTTPS":[!0,"Redirect to the HTTPS version of 4chan."],"JSON Index":[!0,"Replace the original board index with one supporting searching, sorting, infinite scrolling, and a catalog mode."],[`Use ${e.name} Catalog`]:[!0,`Link to ${e.name}'s catalog instead of the native 4chan one.`,1],"Index Refresh Notifications":[!1,"Show a notice at the top of the page when the index is refreshed.",1],"Follow Cursor":[!0,"Image Hover and Quote Preview move with the mouse cursor."],"Open Threads in New Tab":[!1,`Make links to threads in the index / ${e.name} catalog open in a new tab.`],
"External Catalog":[!1,"Link to external catalog instead of the internal one."],"Catalog Links":[!1,"Add toggle link in header menu to turn Navigation links into links to each board's catalog."],"Announcement Hiding":[!0,"Add button to hide 4chan announcements."],"Desktop Notifications":[!0,`Enables desktop notifications across various ${e.name} features.`],"404 Redirect":[!0,"Redirect dead threads and images to the archives."],"Archive Report":[!0,"Enable reporting posts to supported archives."],"Exempt Archives from Encryption":[!0,"Permit loading content from, and warningless redirects to, HTTP-only archives from HTTPS pages."],Keybinds:[!0,"Bind actions to keyboard shortcuts."],"Time Formatting":[!0,"Localize and format timestamps."],"Relative Post Dates":[!0,'Display dates like "3 minutes ago". Tooltip shows the timestamp.'],"Relative Date Title":[!0,"Show Relative Post Date only when hovering over dates.",1],
"Comment Expansion":[!0,"Expand comments that are too long to display on the index. Not applicable with JSON Index."],"File Info Formatting":[!0,"Reformat the file information."],"Thread Expansion":[!0,"Add buttons to expand threads."],"Index Navigation":[!1,"Add buttons to navigate between threads."],"Reply Navigation":[!1,"Add buttons to navigate to top / bottom of thread."],"Unique ID and Capcode Navigation":[!1,"Add buttons to navigate to posts having the same unique ID or capcode."],"Custom Board Titles":[!0,"Allow editing of the board title and subtitle by ctrl/⌘+clicking them."],"Persistent Custom Board Titles":[!1,"Force custom board titles to be persistent, even if the board titles are updated.",1],"Show Updated Notifications":[!0,`Show notifications when ${e.name} is successfully updated.`],"Color User IDs":[!0,"Assign unique colors to user IDs on boards that use them"],"Count Posts by ID":[!0,"Display number of posts in the thread when hovering over an ID."],
@ -404,10 +404,10 @@ textContent:this.summaryText("",n,o),href:`/${e}/thread/${t}`})},thread(e,t,n){l
;return e.OP.highlights&&Ve.addClass(m,...e.OP.highlights),e.OP.file||Ve.addClass(m,"noFile"),m.style.cssText=a||"",m},catalogReply(e,t){let n="";t.com&&(n=this.parseCommentDisplay(t.com).replace(/>>\d+/g,"").trim().replace(/\n+/g," // ")),t.ext&&(n||(n=`${Ve.unescape(t.filename)}${t.ext}`)),t.com&&(n||(n=Ve.unescape(t.com.replace(/<br\b[^<]*>/gi," // ")))),n||(n=" "),n.length>73&&(n=`${n.slice(0,70)}...`);const o=this.postURL(e.board.ID,e.ID,t.no);return Ve.el("div",{className:"catalog-reply"},pe(ue,null,pe("span",null,pe("time",{"data-utc":1e3*t.time,"data-abbrev":"1"},"..."),": "),pe("a",{class:"catalog-reply-excerpt",href:o},n),pe("a",{class:"catalog-reply-preview",href:o},"...")))}}},Ce={tinyboard:ve,yotsuba:Ie};var De={init(){if(["index","thread","archive"].includes(n.VIEW)&&t["File Info Formatting"])return l.Post.push({name:"File Info Formatting",cb:this.node})},node(){if(!this.file)return;if(this.isClone){let e
;for(e of u(".file-info .download-button",this.file.text))Ve.on(e,"click",j.download);for(e of u(".file-info .quick-filter-md5",this.file.text))Ve.on(e,"click",We.quickFilterMD5);return}const e=Ve.el("span",{className:"fileText-original"});Ve.prepend(this.file.link.parentNode,e),Ve.add(e,[this.file.link.previousSibling,this.file.link,this.file.link.nextSibling]);const n=Ve.el("span",{className:"file-info"});return De.format(t.fileInfo,this,n),Ve.prepend(this.file.text,n)},format(e,t,n){let a;const i=[];for(a of(e.replace(/%(.)|[^%]+/g,(function(e,n){return i.push(Ve.hasOwn(De.formatters,n)?De.formatters[n].call(t):{innerHTML:o(e)}),""})),Ve.extend(n,{innerHTML:o.cat(i)}),u(".download-button",n)))Ve.on(a,"click",j.download);for(a of u(".quick-filter-md5",n))Ve.on(a,"click",We.quickFilterMD5)},formatters:{t(){return{innerHTML:o(this.file.url.match(/[^/]*$/)[0]),[ce]:!0}},T(){return pe("a",{href:this.file.url,target:"_blank"},De.formatters.t.call(this))},l(){return pe("a",{
href:this.file.url,target:"_blank"},De.formatters.n.call(this))},L(){return pe("a",{href:this.file.url,target:"_blank"},De.formatters.N.call(this))},n(){const e=this.file.name,t=Ce.yotsuba.Build.shortFilename(this.file.name,this.isReply);return e===t?{innerHTML:o(e),[ce]:!0}:pe("span",{class:"fnswitch"},pe("span",{class:"fntrunc"},t),pe("span",{class:"fnfull"},e))},N(){return{innerHTML:o(this.file.name),[ce]:!0}},d(){return pe("a",{href:this.file.url,download:this.file.name,class:"download-button"},"📥︎")},f:()=>({innerHTML:'<a href="javascript:;" class="quick-filter-md5">✕</a>',[ce]:!0}),p(){return{innerHTML:this.file.isSpoiler?"Spoiler, ":"",[ce]:!0}},s(){return{innerHTML:o(this.file.size),[ce]:!0}},B(){return{innerHTML:Math.round(this.file.sizeInBytes)+" Bytes",[ce]:!0}},K(){return{innerHTML:Math.round(this.file.sizeInBytes/1024)+" KB",[ce]:!0}},M(){return{innerHTML:Math.round(this.file.sizeInBytes/1048576*100)/100+" MB",[ce]:!0}},r(){return{innerHTML:o(this.file.dimensions||"PDF"),
[ce]:!0}},g(){return{innerHTML:this.file.tag?", "+o(this.file.tag):"",[ce]:!0}},"%":()=>({innerHTML:"%",[ce]:!0})}},Ee={init(){["index","thread","archive"].includes(n.VIEW)&&t["Time Formatting"]&&l.Post.push({name:"Time Formatting",cb:this.node})},node(){if(!this.info.date||this.isClone)return;const{textContent:e}=this.nodes.date;this.nodes.date.textContent=e.match(/^\s*/)[0]+Ee.format(t.time,this.info.date)+e.match(/\s*$/)[0]},format:(e,t)=>e.replace(/%(.)/g,(function(e,n){return Ve.hasOwn(Ee.formatters,n)?Ee.formatters[n].call(t):e})),zeroPad:e=>e<10?`0${e}`:e,formatterCache:new Map,formatters:{a(){let e=Ee.formatterCache.get("a");return e||(e=Intl.DateTimeFormat(t.timeLocale,{weekday:"short"}),Ee.formatterCache.set("a",e)),e.format(this)},A(){let e=Ee.formatterCache.get("A");return e||(e=Intl.DateTimeFormat(t.timeLocale,{weekday:"long"}),Ee.formatterCache.set("A",e)),e.format(this)},b(){let e=Ee.formatterCache.get("b");return e||(e=Intl.DateTimeFormat(t.timeLocale,{month:"short"}),
Ee.formatterCache.set("b",e)),e.format(this)},B(){let e=Ee.formatterCache.get("B");return e||(e=Intl.DateTimeFormat(t.timeLocale,{month:"long"}),Ee.formatterCache.set("B",e)),e.format(this)},d(){return Ee.zeroPad(this.getDate())},e(){return this.getDate()},H(){return Ee.zeroPad(this.getHours())},I(){return Ee.zeroPad(this.getHours()%12||12)},k(){return this.getHours()},l(){return this.getHours()%12||12},m(){return Ee.zeroPad(this.getMonth()+1)},M(){return Ee.zeroPad(this.getMinutes())},p(){let e=Ee.formatterCache.get("p");e||(e=Intl.DateTimeFormat(t.timeLocale,{hour:"numeric",hour12:!0}),Ee.formatterCache.set("p",e));return e.formatToParts(this).find((e=>"dayPeriod"===e.type)).value},P(){return Ee.formatters.p.call(this).toLowerCase()},S(){return Ee.zeroPad(this.getSeconds())},y(){return this.getFullYear().toString().slice(2)},Y(){return this.getFullYear()},"%":()=>"%"}},Se={init(){if("thread"!==n.VIEW||!t["Reply Pruning"])return;this.container=Ve.frag(),this.summary=Ve.el("span",{
hidden:!0,className:"summary"}),this.summary.style.cursor="pointer",Ve.on(this.summary,"click",(()=>(this.inputs.enabled.checked=!this.inputs.enabled.checked,Ve.event("change",null,this.inputs.enabled))));const e=L.checkbox("Prune Replies","Show Last",t["Prune All Threads"]),a=Ve.el("span",{title:"Maximum number of replies to show."},{innerHTML:' <input type="number" name="Max Replies" min="0" step="1" value="'+o(t["Max Replies"])+'" class="field">'});return Ve.prepend(a,e),this.inputs={enabled:e.firstElementChild,replies:a.lastElementChild},this.setEnabled.call(this.inputs.enabled),Ve.on(this.inputs.enabled,"change",this.setEnabled),Ve.on(this.inputs.replies,"change",Ve.cb.value),Ke.menu.addEntry({el:a,order:190}),l.Thread.push({name:"Reply Pruning",cb:this.node})},position:0,hidden:0,hiddenFiles:0,total:0,totalFiles:0,setEnabled(){const e=Te.input;return this.checked&&e?.checked&&(e.checked=!1,Ve.event("change",null,e)),Se.active=this.checked},showIfHidden(e){
if(Se.container&&Ve(`#${e}`,Se.container))return Se.inputs.enabled.checked=!1,Ve.event("change",null,Se.inputs.enabled)},node(){let e;return Se.thread=this,this.isSticky&&(Se.active=Se.inputs.enabled.checked=!0,Te.input&&(t["Thread Quotes"]=Te.input.checked=!1)),this.posts.forEach((function(e){if(e.isReply&&(Se.total++,e.file))return Se.totalFiles++})),Se.active&&/^#p\d+$/.test(location.hash)&&1<=(e=this.posts.keys.indexOf(location.hash.slice(2)))&&e<1+Math.max(Se.total-+t["Max Replies"],0)&&(Se.active=Se.inputs.enabled.checked=!1),Ve.after(this.OP.nodes.root,Se.summary),Ve.on(Se.inputs.enabled,"change",Se.update),Ve.on(Se.inputs.replies,"change",Se.update),Ve.on(a,"ThreadUpdate",Se.updateCount),Ve.on(a,"ThreadUpdate",Se.update),Se.update()},updateCount(e){if(!e.detail[404])for(var t of e.detail.newPosts)Se.total++,n.posts.get(t).file&&Se.totalFiles++},update(){let e,o,i
[ce]:!0}},g(){return{innerHTML:this.file.tag?", "+o(this.file.tag):"",[ce]:!0}},"%":()=>({innerHTML:"%",[ce]:!0})}},Ee={init(){["index","thread","archive"].includes(n.VIEW)&&t["Time Formatting"]&&l.Post.push({name:"Time Formatting",cb:this.node})},node(){if(!this.info.date||this.isClone)return;const{textContent:e}=this.nodes.date;this.nodes.date.textContent=e.match(/^\s*/)[0]+Ee.format(t.time,this.info.date)+e.match(/\s*$/)[0]},format:(e,t)=>e.replace(/%(.)/g,(function(e,n){return Ve.hasOwn(Ee.formatters,n)?Ee.formatters[n].call(t):e})),zeroPad:e=>e<10?`0${e}`:e,formatterCache:new Map,formatters:{a(){let e=Ee.formatterCache.get("a");return e||(e=Intl.DateTimeFormat(t.timeLocale||void 0,{weekday:"short"}),Ee.formatterCache.set("a",e)),e.format(this)},A(){let e=Ee.formatterCache.get("A");return e||(e=Intl.DateTimeFormat(t.timeLocale||void 0,{weekday:"long"}),Ee.formatterCache.set("A",e)),e.format(this)},b(){let e=Ee.formatterCache.get("b")
;return e||(e=Intl.DateTimeFormat(t.timeLocale||void 0,{month:"short"}),Ee.formatterCache.set("b",e)),e.format(this)},B(){let e=Ee.formatterCache.get("B");return e||(e=Intl.DateTimeFormat(t.timeLocale||void 0,{month:"long"}),Ee.formatterCache.set("B",e)),e.format(this)},d(){return Ee.zeroPad(this.getDate())},e(){return this.getDate()},H(){return Ee.zeroPad(this.getHours())},I(){return Ee.zeroPad(this.getHours()%12||12)},k(){return this.getHours()},l(){return this.getHours()%12||12},m(){return Ee.zeroPad(this.getMonth()+1)},M(){return Ee.zeroPad(this.getMinutes())},p(){let e=Ee.formatterCache.get("p");e||(e=Intl.DateTimeFormat(t.timeLocale||void 0,{hour:"numeric",hour12:!0}),Ee.formatterCache.set("p",e));return e.formatToParts(this).find((e=>"dayPeriod"===e.type)).value},P(){return Ee.formatters.p.call(this).toLowerCase()},S(){return Ee.zeroPad(this.getSeconds())},y(){return this.getFullYear().toString().slice(2)},Y(){return this.getFullYear()},"%":()=>"%"}},Se={init(){
if("thread"!==n.VIEW||!t["Reply Pruning"])return;this.container=Ve.frag(),this.summary=Ve.el("span",{hidden:!0,className:"summary"}),this.summary.style.cursor="pointer",Ve.on(this.summary,"click",(()=>(this.inputs.enabled.checked=!this.inputs.enabled.checked,Ve.event("change",null,this.inputs.enabled))));const e=L.checkbox("Prune Replies","Show Last",t["Prune All Threads"]),a=Ve.el("span",{title:"Maximum number of replies to show."},{innerHTML:' <input type="number" name="Max Replies" min="0" step="1" value="'+o(t["Max Replies"])+'" class="field">'});return Ve.prepend(a,e),this.inputs={enabled:e.firstElementChild,replies:a.lastElementChild},this.setEnabled.call(this.inputs.enabled),Ve.on(this.inputs.enabled,"change",this.setEnabled),Ve.on(this.inputs.replies,"change",Ve.cb.value),Ke.menu.addEntry({el:a,order:190}),l.Thread.push({name:"Reply Pruning",cb:this.node})},position:0,hidden:0,hiddenFiles:0,total:0,totalFiles:0,setEnabled(){const e=Te.input
;return this.checked&&e?.checked&&(e.checked=!1,Ve.event("change",null,e)),Se.active=this.checked},showIfHidden(e){if(Se.container&&Ve(`#${e}`,Se.container))return Se.inputs.enabled.checked=!1,Ve.event("change",null,Se.inputs.enabled)},node(){let e;return Se.thread=this,this.isSticky&&(Se.active=Se.inputs.enabled.checked=!0,Te.input&&(t["Thread Quotes"]=Te.input.checked=!1)),this.posts.forEach((function(e){if(e.isReply&&(Se.total++,e.file))return Se.totalFiles++})),Se.active&&/^#p\d+$/.test(location.hash)&&1<=(e=this.posts.keys.indexOf(location.hash.slice(2)))&&e<1+Math.max(Se.total-+t["Max Replies"],0)&&(Se.active=Se.inputs.enabled.checked=!1),Ve.after(this.OP.nodes.root,Se.summary),Ve.on(Se.inputs.enabled,"change",Se.update),Ve.on(Se.inputs.replies,"change",Se.update),Ve.on(a,"ThreadUpdate",Se.updateCount),Ve.on(a,"ThreadUpdate",Se.update),Se.update()},updateCount(e){if(!e.detail[404])for(var t of e.detail.newPosts)Se.total++,n.posts.get(t).file&&Se.totalFiles++},update(){let e,o,i
;const r=Se.hidden,s=Se.active?Math.max(Se.total-+t["Max Replies"],0):0,l=a.body.clientHeight-window.scrollY,{posts:d}=Se.thread;if(Se.hidden<s){for(;Se.hidden<s&&Se.position<d.keys.length;)if(i=d.get(d.keys[Se.position++]),i.isReply&&!i.isFetchedQuote){for(;(o=Se.summary.nextSibling)&&o!==i.nodes.root;)Ve.add(Se.container,o);Ve.add(Se.container,i.nodes.root),Se.hidden++,i.file&&Se.hiddenFiles++}}else if(Se.hidden>s){const e=Ve.frag();for(;Se.hidden>s&&Se.position>0;)if(i=d.get(d.keys[--Se.position]),i.isReply&&!i.isFetchedQuote){for(;(o=Se.container.lastChild)&&o!==i.nodes.root;)Ve.prepend(e,o);Ve.prepend(e,i.nodes.root),Se.hidden--,i.file&&Se.hiddenFiles--}Ve.after(Se.summary,e),Ve.event("PostsInserted",null,Se.summary.parentNode)}if(Se.summary.textContent=Se.active?n.SITE.Build.summaryText("+",Se.hidden,Se.hiddenFiles):n.SITE.Build.summaryText("-",Se.total,Se.totalFiles),Se.summary.hidden=Se.total<=+t["Max Replies"],
r!==s&&(e=Ke.getTopOf(Ve(".board")))<0)return window.scrollBy(0,Math.max(a.body.clientHeight-l,window.scrollY+e)-window.scrollY)}},Te={init(){if(t["Quote Threading"]&&"thread"===n.VIEW)return this.controls=Ve.el("label",{innerHTML:'<input id="threadingControl" name="Thread Quotes" type="checkbox"> Threading'}),this.threadNewLink=Ve.el("span",{className:"brackets-wrap threadnewlink",hidden:!0}),Ve.extend(this.threadNewLink,{innerHTML:'<a href="javascript:;">Thread New Posts</a>'}),this.input=Ve("input",this.controls),this.input.checked=t["Thread Quotes"],Ve.on(this.input,"change",this.setEnabled),Ve.on(this.input,"change",this.rethread),Ve.on(this.threadNewLink.firstElementChild,"click",this.rethread),Ve.on(a,"4chanXInitFinished",(()=>this.ready=!0)),Ke.menu.addEntry(this.entry={el:this.controls,order:99}),l.Thread.push({name:"Quote Threading",cb:this.setThread}),l.Post.push({name:"Quote Threading",cb:this.node})},parent:m(),children:m(),inserted:m(),toggleThreading(){
return this.setThreadingState(!t["Thread Quotes"])},setThreadingState(e){return this.input.checked=e,this.setEnabled.call(this.input),this.rethread.call(this.input)},setEnabled(){if(this.checked){Ve.set("Prune All Threads",!1);const e=Se.inputs?.enabled;e?.checked&&(e.checked=!1,Ve.event("change",null,e))}return Ve.cb.checked.call(this)},setThread(){return Te.thread=this,Ve.asap((()=>!t["Thread Updater"]||Ve(".navLinksBot > .updatelink")),(function(){let e;if(e=Ve(".navLinksBot"))return Ve.add(e,[Ve.tn(" "),Te.threadNewLink])}))},node(){let e;if(this.isFetchedQuote||this.isClone||!this.isReply)return;const t=new Set;let o=null;for(var a of this.quotes)(e=n.posts.get(a))&&!e.isFetchedQuote&&e.isReply&&e.ID<this.ID&&(t.add(e.ID),(!o||e.ID>o.ID)&&(o=e));if(!o)return;let i=o;for(;i=Te.parent[i.fullID];)t.delete(i.ID);return 1===t.size?Te.parent[this.fullID]=o:void 0},descendants(e){let t,n=[e];if(t=Te.children[e.fullID])for(var o of t)n=n.concat(Te.descendants(o));return n},insert(e){

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "4chan XT",
"version": "XT 2.0.1",
"version": "XT 2.1.1",
"manifest_version": 2,
"description": "4chan XT is a script that adds various features to anonymous imageboards.",
"icons": {

View File

@ -79,8 +79,8 @@
'use strict';
var version = {
"version": "XT 2.0.1",
"date": "2023-06-24T16:01:33.425Z"
"version": "XT 2.1.1",
"date": "2023-07-16T08:49:02.722Z"
};
var meta = {
@ -93,8 +93,8 @@
"faq": "https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions",
"captchaFAQ": "https://github.com/ccd0/4chan-x/wiki/Captcha-FAQ",
"cssGuide": "https://github.com/ccd0/4chan-x/wiki/Styling-Guide",
"license": "https://github.com/TuxedoTako/4chan-xt/blob/master/LICENSE",
"changelog": "https://github.com/TuxedoTako/4chan-xt/blob/master/CHANGELOG.md",
"license": "https://github.com/TuxedoTako/4chan-xt/blob/project-XT/LICENSE",
"changelog": "https://github.com/TuxedoTako/4chan-xt/blob/project-XT/CHANGELOG.md",
"issues": "https://github.com/TuxedoTako/4chan-xt/issues",
"newIssue": "https://github.com/TuxedoTako/4chan-xt/issues",
"newIssueMaxLength": 8181,
@ -14173,7 +14173,8 @@ $\
a() {
let formatter = Time.formatterCache.get('a');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], { weekday: 'short' });
// || undefined to fall back to browser locale, an empty string gives an error
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, { weekday: 'short' });
Time.formatterCache.set('a', formatter);
}
return formatter.format(this);
@ -14181,7 +14182,7 @@ $\
A() {
let formatter = Time.formatterCache.get('A');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], { weekday: 'long' });
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, { weekday: 'long' });
Time.formatterCache.set('A', formatter);
}
return formatter.format(this);
@ -14189,7 +14190,7 @@ $\
b() {
let formatter = Time.formatterCache.get('b');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], { month: 'short' });
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, { month: 'short' });
Time.formatterCache.set('b', formatter);
}
return formatter.format(this);
@ -14197,7 +14198,7 @@ $\
B() {
let formatter = Time.formatterCache.get('B');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], { month: 'long' });
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, { month: 'long' });
Time.formatterCache.set('B', formatter);
}
return formatter.format(this);
@ -14213,7 +14214,7 @@ $\
p() {
let formatter = Time.formatterCache.get('p');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], { hour: 'numeric', hour12: true });
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, { hour: 'numeric', hour12: true });
Time.formatterCache.set('p', formatter);
}
const parts = formatter.formatToParts(this);

View File

@ -11,8 +11,8 @@
"faq": "https://github.com/ccd0/4chan-x/wiki/Frequently-Asked-Questions",
"captchaFAQ": "https://github.com/ccd0/4chan-x/wiki/Captcha-FAQ",
"cssGuide": "https://github.com/ccd0/4chan-x/wiki/Styling-Guide",
"license": "https://github.com/TuxedoTako/4chan-xt/blob/master/LICENSE",
"changelog": "https://github.com/TuxedoTako/4chan-xt/blob/master/CHANGELOG.md",
"license": "https://github.com/TuxedoTako/4chan-xt/blob/project-XT/LICENSE",
"changelog": "https://github.com/TuxedoTako/4chan-xt/blob/project-XT/CHANGELOG.md",
"issues": "https://github.com/TuxedoTako/4chan-xt/issues",
"newIssue": "https://github.com/TuxedoTako/4chan-xt/issues",
"newIssueMaxLength": 8181,

View File

@ -38,7 +38,8 @@ var Time = {
a() {
let formatter = Time.formatterCache.get('a');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], {weekday: 'short'});
// || undefined to fall back to browser locale, an empty string gives an error
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, {weekday: 'short'});
Time.formatterCache.set('a', formatter)
}
return formatter.format(this);
@ -46,7 +47,7 @@ var Time = {
A() {
let formatter = Time.formatterCache.get('A');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], {weekday: 'long'});
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, {weekday: 'long'});
Time.formatterCache.set('A', formatter)
}
return formatter.format(this);
@ -54,7 +55,7 @@ var Time = {
b() {
let formatter = Time.formatterCache.get('b');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], {month: 'short'});
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, {month: 'short'});
Time.formatterCache.set('b', formatter)
}
return formatter.format(this);
@ -62,7 +63,7 @@ var Time = {
B() {
let formatter = Time.formatterCache.get('B');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], {month: 'long'});
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, {month: 'long'});
Time.formatterCache.set('B', formatter)
}
return formatter.format(this);
@ -78,7 +79,7 @@ var Time = {
p() {
let formatter = Time.formatterCache.get('p');
if (!formatter) {
formatter = Intl.DateTimeFormat(Conf['timeLocale'], {hour: 'numeric', hour12: true});
formatter = Intl.DateTimeFormat(Conf['timeLocale'] || undefined, {hour: 'numeric', hour12: true});
Time.formatterCache.set('p', formatter)
}
const parts = formatter.formatToParts(this);

View File

@ -1,4 +1,4 @@
{
"version": "XT 2.0.1",
"date": "2023-06-24T16:01:33.425Z"
"version": "XT 2.1.1",
"date": "2023-07-16T08:49:02.722Z"
}