`)).join(""))},handleFileRemove(e){const t=+e.currentTarget.getAttribute("data-idx"),a=e.currentTarget.closest(`.${ns}-file-input`).querySelector('input[type="file"]'),n=new DataTransfer;for(let e=0;e{const a=e.type.startsWith("video"),n=e.type.startsWith("image")||"video/webm"===e.type,s=e.type.startsWith("audio");if(a||n||s){const a="video/webm"===e.type&&t?t:n?Player.tools.imgInput:Player.tools.sndInput,s=new DataTransfer;a.multiple&&[...a.files].forEach((e=>s.items.add(e))),s.items.add(e),a.files=s.files,Player.tools.handleFileSelect(a),a===Player.tools.imgInput&&Player.tools.handleImageSelect(),a===Player.tools.sndInput&&Player.tools.useSoundURL&&Player.tools.toggleSoundInput("file")}})),!1},async handleCreate(){Player.tools._createdImageURL&&URL.revokeObjectURL(Player.tools._createdImageURL),Player.tools._createdImage=null,o.status.style.display="block",o.status.innerHTML="Creating sound image",Player.$(`.${ns}-create-button`).disabled=!0;const e=Player.config.uploadHosts[Player.$(`.${ns}-create-sound-host`).value],t=Player.tools.useSoundURL;let a=Player.tools.imgInput.files[0],s=t&&Player.$(`.${ns}-create-sound-snd-url`).value.split(",").map((e=>e.trim())).filter((e=>e)),l=(Player.$(`.${ns}-use-video`)||{}).checked&&a&&a.type.startsWith("video")?a&&[a]:[...Player.tools.sndInput.files];const i=Player.$(`.${ns}-create-sound-name`).value,d=i?((s||l).length>1?i.split(","):[i]).map((e=>e.trim())):a&&[a.name.replace(/\.[^/.]+$/,"")];try{if(!a)throw new PlayerError("Select an image or webm.","warning");if(a.type.startsWith("video")&&await Player.tools.hasAudio(a))throw o.status.innerHTML+=" Audio not allowed for the image webm. Remove the audio from the webm and try again.",new PlayerError("Audio not allowed for the image webm.","warning");const i=d.join("").length+8*(s||l).length;if(t){try{s=s.map((e=>new URL(e)&&e.replace(/^(https?:)?\/\//,"")))}catch(e){throw new PlayerError("The provided sound URL is invalid.","warning")}if(2188)throw new PlayerError("The generated image filename is too long.","warning");l=await Promise.all(l.map((async e=>{if(e.type.startsWith("video")&&!await Player.tools.hasAudio(e))throw new PlayerError(`The selected video has no audio. (${e.name})`,"warning");return e})));try{s=await Promise.all(l.map((async t=>Player.tools.postFile(t,e))))}catch(e){throw new PlayerError("Upload failed.","error",e)}}if(!s.length)throw new PlayerError("No sounds selected.","warning");let c="";for(let e=0;eFailed! "+(e instanceof PlayerError?e.reason:""),Player.logError("Failed to create sound image",e)}Player.$(`.${ns}-create-button`).disabled=!1},hasAudio:e=>!(!e.type.startsWith("audio")&&!e.type.startsWith("video"))&&new Promise(((t,a)=>{const n=URL.createObjectURL(e),s=document.createElement("video");s.addEventListener("loadeddata",(()=>{URL.revokeObjectURL(n),t(s.mozHasAudio||!!s.webkitAudioDecodedByteCount)})),s.addEventListener("error",a),s.src=n})),async postFile(e,t){const a=Player.tools._uploadIdx++;if(!t||t.invalid)throw new PlayerError("Invalid upload host.","error");const s=new FormData;return Object.keys(t.data).forEach((a=>{null!==t.data[a]&&s.append(a,"$file"===t.data[a]?e:t.data[a])})),o.status.innerHTML+=` Uploading ${e.name}`,new Promise(((r,l)=>{GM.xmlHttpRequest({method:"POST",url:t.url,data:s,responseType:t.responsePath?"json":"text",headers:t.headers,onload:async s=>{if(s.status<200||s.status>=300)return l(s);const o=t.responsePath?n.get(s.response,t.responsePath):t.responseMatch?(s.responseText.match(new RegExp(t.responseMatch))||[])[1]:s.responseText,i=(t.soundUrl?t.soundUrl.replace("%s",o):o).trim();Player.$(`.${ns}-upload-status-${a}`).innerHTML=`Uploaded ${e.name} to ${i}`,r(i)},upload:{onprogress:t=>{const n=t.total>0?t.total:e.size;Player.$(`.${ns}-upload-status-${a}`).innerHTML=`Uploading ${e.name} - ${Math.floor(t.loaded/n*100)}%`}},onerror:l})}))},addCreatedToPlayer(){Player.playlist.addFromFiles([Player.tools._createdImage])},addCreatedToQR(){if(!is4chan)return;const e=document.querySelector(isChanX?".qr-link":".open-qr-link"),t=new DataTransfer;if(t.items.add(Player.tools._createdImage),isChanX&&e){e.click();const a=new CustomEvent("drop",{view:window,bubbles:!0,cancelable:!0});a.dataTransfer=t,document.querySelector("#qr").dispatchEvent(a)}else e?(e.click(),document.querySelector("#qrFile").files=t.files):(document.querySelector("#togglePostFormLink a").click(),document.querySelector("#postFile").files=t.files,document.querySelector(".postForm").scrollIntoView())}}},6533:(e,t,a)=>{var n=a(6325);const s=a(5563),r=(e,t)=>{let a,n=new Promise(((n,s)=>{a=GM.xmlHttpRequest({method:"GET",url:e,responseType:"blob",onload:e=>n(e.response),onerror:e=>s(e),onabort:e=>{e.aborted=!0,s(e)},...t||{}})}));return t&&t.catch&&(n=n.catch(t.catch)),n.abort=a.abort,n},l=e.exports={downloadTemplate:a(4805),_downloading:null,initialize(){Player.on("rendered",l.afterRender)},afterRender(){l.resetDownloadButtons()},async _handleDownloadCancel(){Player.tools._downloading&&(Player.tools._downloadAllCanceled=!0,Player.tools._downloading.forEach((e=>e.forEach((e=>e&&e.abort())))))},async _handleDownload(e){Player.tools._downloadAllCanceled=!1,e.currentTarget.style.display="none",Player.$(`.${ns}-download-all-cancel`).style.display=null,await Player.tools.downloadThread({includeImages:Player.$(".download-all-images").checked,includeSounds:Player.$(".download-all-audio").checked,ignoreDownloaded:Player.$(".download-all-ignore-downloaded").checked,maxSounds:+Player.$(".download-all-max-sounds").value||0,concurrency:Math.max(1,+Player.$(".download-all-concurrency").value||1),compression:Math.max(0,Math.min(+Player.$(".download-all-compression").value||0,9)),status:Player.$(`.${ns}-download-all-status`)}).catch((()=>{})),Player.tools.resetDownloadButtons()},resetDownloadButtons(){Player.$(`.${ns}-download-all-start`).style.display=Player.tools._downloading?"none":null,Player.$(`.${ns}-download-all-cancel`).style.display=Player.tools._downloading?null:"none",Player.$(`.${ns}-download-all-save`).style.display=Player.tools.threadDownloadBlob?null:"none",Player.$(`.${ns}-download-all-clear`).style.display=Player.tools.threadDownloadBlob?null:"none",Player.$(`.${ns}-ignore-downloaded`).style.display=Player.sounds.some((e=>e.downloaded))?null:"none"},async download(e,t){try{const a=await r(e),s=n.element(``);s.click(),URL.revokeObjectURL(s.href)}catch(e){Player.logError("There was an error downloading.",e,"warning")}},async downloadThread({includeImages:e,includeSounds:t,ignoreDownloaded:a,maxSounds:l,concurrency:o,compression:i,status:d}){const c=new JSZip;!(l>0)&&(l=1/0);const p=Player.sounds.filter((e=>e.post&&(!a||!e.downloaded))).slice(0,l),y=p.length;if(d&&(d.style.display="block"),!y||!e&&!t)return d&&(d.innerHTML="Nothing to download.");Player.tools._downloading=[],d&&(d.innerHTML=`Downloading ${y} sound images.
\n\t\t\tThis may take a while. You can leave it running in the background, but if you background the tab your browser will slow it down.\n\t\t\tYou'll be prompted to download the zip file once complete.
`,u[0].el,"beforebegin"):(m&&c.file(`${i}${l.filename}`,m),v&&c.file(`${i}${encodeURIComponent(l.src)}`,v),l.downloaded=!0)),await a(s)}))),Player.tools._downloadAllCanceled&&n.element(`Canceled at ${h} / ${y}.`,d);const m=d&&n.element("
Generating zip file...
",d);try{const e={type:"blob",compression:i?"DEFLATE":"STORE",compressionOptions:{level:i}};Player.tools.threadDownloadBlob=await c.generateAsync(e,(e=>{d&&(m.textContent=`Generating zip file (${e.percent.toFixed(2)}%)...`)})),d&&n.element("Complete!",d),Player.tools.saveThreadDownload()}catch(e){console.error("[4chan sounds player] Failed to generate zip",e),d&&(m.textContent="Failed to generate zip file!")}Player.tools._downloading=null,Player.tools.resetDownloadButtons()},saveThreadDownload(){const e=Thread||"-",t=n.element(``);t.click(),URL.revokeObjectURL(t.href)},clearDownloadBlob(){delete Player.tools.threadDownloadBlob,Player.tools.resetDownloadButtons()}}},5305:(e,t,a)=>{var n=a(6325);const s=a(8433),r=a(6533);e.exports={template:a(2230),...s,...r,initialize(){s.initialize(),r.initialize()},render(){n.elementHTML(Player.$(`.${ns}-tools`).innerHTML,Player.tools.template()),s.afterRender(),r.afterRender()},toggle(){"tools"===Player.config.viewStyle?Player.playlist.restore():Player.display.setViewStyle("tools")},handleDecoded(e){Player.$(`.${ns}-encoded-input`).value=encodeURIComponent(e.currentTarget.value)},handleEncoded(e){Player.$(`.${ns}-decoded-input`).value=decodeURIComponent(e.currentTarget.value)}}},5535:(e,t,a)=>{var n=a(4302),s=a(6325);const{postIdPrefix:r}=a(218);e.exports=[{property:"repeat",tplName:"repeat",action:"playlist.toggleRepeat",actionMods:".prevent",values:{all:{attrs:['title="Repeat All"'],icon:n.arrowRepeat},one:{attrs:['title="Repeat One"'],icon:n.arrowClockwise},none:{attrs:['title="No Repeat"'],class:"muted",icon:n.arrowRepeat}}},{property:"shuffle",tplName:"shuffle",action:"playlist.toggleShuffle",actionMods:".prevent",values:{true:{attrs:['title="Shuffled"'],icon:n.shuffle},false:{attrs:['title="Ordered"'],class:"muted",icon:n.shuffle}}},{property:"viewStyle",tplName:"playlist",action:"playlist.toggleView",values:{default:{attrs:['title="Player"'],class:"muted",icon:()=>"playlist"===Player.playlist._lastView?n.arrowsExpand:n.arrowsCollapse},playlist:{attrs:['title="Hide Playlist"'],icon:n.arrowsExpand},image:{attrs:['title="Show Playlist"'],icon:n.arrowsCollapse}}},{property:"hoverImages",tplName:"hover-images",action:"playlist.toggleHoverImages",values:{true:{attrs:['title="Hover Images Enabled"'],icon:n.image},false:{attrs:['title="Hover Images Disabled"'],class:"muted",icon:n.image}}},{tplName:"add",action:"playlist.selectLocalFiles",actionMods:".prevent",icon:n.plus,attrs:['title="Add local files"']},{tplName:"reload",action:"posts.refresh",actionMods:".prevent",icon:n.reboot,attrs:['title="Reload the playlist"']},{property:"viewStyle",tplName:"settings",action:"settings.toggle()",actionMods:".prevent",icon:n.gear,attrs:['title="Settings"'],values:{default:{class:"muted"},settings:{}}},{property:"viewStyle",tplName:"threads",action:"threads.toggle",actionMods:".prevent",icon:n.search,attrs:['title="Threads"'],values:{default:{class:"muted"},threads:{}}},{property:"viewStyle",tplName:"tools",action:"tools.toggle",actionMods:".prevent",icon:n.tools,attrs:['title="Tools"'],values:{default:{class:"muted"},tools:{}}},{tplName:"close",action:"hide",actionMods:".prevent",icon:n.close,attrs:['title="Hide the player"']},{tplName:"playing",requireSound:!0,action:'playlist.scrollToPlaying("center")',actionMods:".prevent",icon:n.musicNoteList,attrs:['title="Scroll the playlist to the currently playing sound."']},{tplName:"post",requireSound:!0,icon:n.chatRightQuote,showIf:e=>e.sound.post,attrs:e=>["href="+("#"+r+e.sound.post),'title="Jump to the post for the current sound"']},{tplName:"image",requireSound:!0,icon:n.image,attrs:e=>[`href=${e.sound.image}`,'title="Open the image in a new tab"','target="_blank"']},{tplName:"sound",requireSound:!0,icon:n.soundwave,attrs:e=>[`href=${e.sound.src}`,'title="Open the sound in a new tab"','target="_blank"']},{tplName:/dl-(image|sound)/,requireSound:!0,action:e=>{const t=e.sound["image"===e.tplNameMatch[1]?"image":"src"],a=e.sound["image"===e.tplNameMatch[1]?"filename":"name"]||"";return`tools.download("${s.escAttr(t,!0)}", "${s.escAttr(a,!0)}")`},actionMods:".prevent",icon:e=>"image"===e.tplNameMatch[1]?n.fileEarmarkImage:n.fileEarmarkMusic,attrs:e=>[`title="${"image"===e.tplNameMatch[1]?"Download the image with the original filename":"Download the sound"}"`]},{tplName:/filter-(image|sound)/,requireSound:!0,action:e=>`playlist.addFilter("${"image"===e.tplNameMatch[1]?e.sound.imageMD5:e.sound.src.replace(/^(https?:)?\/\//,"")}")`,actionMods:".prevent",icon:n.filter,showIf:e=>"sound"===e.tplNameMatch[1]||e.sound.imageMD5,attrs:e=>[`title="Add the ${"image"===e.tplNameMatch[1]?"image MD5":"sound URL"} to the filters."`]},{tplName:"remove",requireSound:!0,action:e=>`remove("${e.sound.id}")`,icon:n.trash,attrs:e=>['title="Filter the image."',`data-id="${e.sound.id}"`]},{tplName:"menu",requireSound:!0,class:`${ns}-item-menu-button`,action:e=>`playlist.handleItemMenu($event, "${e.sound.id}")`,actionMods:".prevent.stop",icon:n.chevronDown},{tplName:"view-menu",action:'display.showMenu($event.currentTarget, "views")',actionMods:".prevent.stop",icon:n.chevronDown,attrs:['title="Switch View"']},{tplName:"theme-menu",action:'display.showMenu($event.currentTarget, "themes")',actionMods:".prevent.stop",icon:n.layoutTextWindow,attrs:['title="Switch Theme"']},{tplName:"untz",action:"display.untz",icon:n.speaker,attrs:['title="UNTZ"']}]},3722:(e,t,a)=>{var n=a(6325);const s=a(5535),r=/p: ?{([^}]*)}/g,l=/h: ?{([^}]*)}/g,o=s.map((e=>`${e.tplName.source&&e.tplName.source.replace(/\(/g,"(?:")||e.tplName}`)),i=new RegExp(`(${o.join("|")})-(?:button|link)(?:\\:"([^"]+?)")?`,"g"),d=/sound-title/g,c=/sound-title-marquee/g,p=/sound-index/g,y=/sound-count/g,u=/sound-(src|id|name|post|imageOrThumb|image|thumb|filename|imageMD5)(-esc)?/g,h=/filtered-count/g,g=/\$config\[([^\]]+)\]/g,m=[];e.exports={buttons:s,initialize(){Player.on("config",Player.userTemplate._handleConfig),Player.on("playsound",(()=>Player.userTemplate._handleEvent("playsound"))),["add","remove","order","show","hide","stop"].forEach((e=>{Player.on(e,Player.userTemplate._handleEvent.bind(null,e))}))},build(e){const t=e.outerClass||"",a=e.sound&&e.sound.title||e.defaultName;let s={...e};const o=e=>"function"==typeof e?e(s):e;let m=e.template.replace(g,((...e)=>n.get(Player.config,e[1])));if(!e.ignoreDisplayBlocks&&(m=m.replace(r,Player.playing&&Player.playing===e.sound?"$1":"").replace(l,`$1`)),!e.ignoreButtons&&(m=m.replace(i,(function(a,r,l){let i=Player.userTemplate._findButtonConf(r);if(s.tplNameMatch=i.tplNameMatch,i.requireSound&&!e.sound||i.showIf&&!i.showIf(s))return"";if(i.values){i={...i,...i.values[n.get(Player.config,i.property)]||i.values[Object.keys(i.values)[0]]}}const d=[...o(i.attrs)||[]];return d.some((e=>e.startsWith("href")))||d.push('href="javascript:;"'),(i.class||t)&&d.push(`class="${i.class||""} ${t||""}"`),i.action&&d.push(`@click${i.actionMods||""}='${o(i.action)}'`),`${l&&l.replace(/ /g," ")||o(i.icon)||o(i.text)}`}))),!e.ignoreSoundName&&(m=m.replace(c,a?`
${a}
`:"").replace(d,a?`
${a}
`:"")),!e.ignoreSoundProperties&&(m=m.replace(u,((...t)=>e.sound?t[2]?n.escAttr(e.sound[t[1]],!0):e.sound[t[1]]:"")).replace(p,e.sound?Player.sounds.indexOf(e.sound)+1:0).replace(y,Player.sounds.length).replace(h,Player.filteredSounds.length)),!e.ignoreVersion&&(m=m.replace(/%v/g,"3.5.4")),e.replacements)for(let t of Object.keys(e.replacements))m=m.replace(new RegExp(t,"g"),e.replacements[t]);return m},maintain(e,t,a=[],n=[]){m.push({component:e,property:t,...Player.userTemplate.findDependencies(t,null),alwaysRenderConfigs:a,alwaysRenderEvents:n})},findDependencies(e,t){t||(t=n.get(Player.config,e));const a=[],s=y.test(t),l=d.test(t)||u.test(t),o=p.test(t),c=r.test(t),m=h.test(t);s&&a.push("add","remove"),"rowTemplate"!==e&&(l||o||c)&&a.push("playsound","stop"),o&&a.push("order"),m&&a.push("filters-applied");const v=[];let f;for(;null!==(f=i.exec(t));)if(!f[2]){let e=Player.userTemplate._findButtonConf(f[1]);e.property&&v.push(e.property)}for(;null!==(f=g.exec(t));)v.push(f[1]);return{events:a,config:v}},_handleConfig(e,t){m.forEach((a=>{a.property===e&&(Object.assign(a,Player.userTemplate.findDependencies(e,t)),a.component.render())})),m.forEach((t=>{(t.alwaysRenderConfigs.includes(e)||t.config.includes(e))&&t.component.render()}))},_handleEvent(e){m.forEach((t=>{(t.alwaysRenderEvents.includes(e)||t.events.includes(e))&&t.component.render()}))},_findButtonConf:e=>{let t,a=s.find((a=>t=a.tplName===e?[e]:a.tplName.test&&e.match(a.tplName)));return a&&{...a,tplNameMatch:t}}}},1277:e=>{e.exports=[{property:"autoshow",default:!0,title:"Autoshow",description:"Automatically show the player when the thread contains sounds.",displayGroup:"Display"},{property:"pauseOnHide",default:!0,title:"Pause On Hide",description:"Pause the player when it's hidden.",displayGroup:"Display",allowInTheme:!0},{property:"showUpdatedNotification",default:!0,title:"Show Update Notifications",description:"Show notifications when the player is successfully updated.",displayGroup:"Display"},{property:"hoverImages",title:"Hover Images",default:!1,allowInTheme:!0},{title:"Controls",displayGroup:"Display",allowInTheme:!0,settings:[{property:"preventControlWrapping",title:"Prevent Wrapping",description:"Hide controls to prevent wrapping when the player is too small",default:!0},{property:"controlsHideOrder",title:"Hide Order",description:'Order controls are hidden in to prevent wrapping. Available controls are
previous
next
seek-bar
time
duration
volume
volume-button
volume-bar
and
fullscreen
.',default:["fullscreen","duration","volume-bar","seek-bar","time","previous"],displayMethod:"textarea",inlineTextarea:!0,format:e=>e.join("\n"),parse:e=>e.split(/\s+/)}]},{title:"Minimised Display",description:"Optional displays for when the player is minimised.",displayGroup:"Display",allowInTheme:!0,settings:[{property:"pip",title:"Thumbnail",description:"Display a fixed thumbnail of the playing sound in the bottom right of the thread.",default:!0},{property:"maxPIPWidth",title:"Max Width",description:"Maximum width for the thumbnail.",default:"150px",updateCSSVars:!0},{property:"chanXControls",title:"4chan X Header Controls",description:"Show playback controls in the 4chan X header. The display can be customised in Settings>Theme.",displayMethod:isChanX||null,default:"closed",options:{always:"Always",closed:"Only with the player closed",never:"Never"}}]},{title:"Thread",displayGroup:"Display",allowInTheme:!0,settings:[{property:"autoScrollThread",description:"Automatically scroll the thread to posts as sounds play.",title:"Auto Scroll",default:!1},{property:"limitPostWidths",description:"Limit the width of posts so they aren't hidden under the player.",title:"Limit Post Widths",default:!0},{property:"minPostWidth",title:"Minimum Width",default:"50%"}]},{property:"threadsViewStyle",title:"Threads View",description:"How threads in the threads view are listed.",settings:[{title:"Display",default:"table",options:{table:"Table",board:"Board"}}]},{title:"Colors",displayGroup:"Display",property:"colors",updateCSSVars:!0,allowInTheme:!0,class:`${ns}-colorpicker-input`,attrs:'@focusout.stop.prevent="colorpicker._updatePreview" @click="colorpicker.create"',displayMethod:({value:e,attrs:t})=>`
\n\t\t\t\t\n\t\t\t\t\n\t\t\t
`,actions:[{title:"Match Theme",handler:"theme.forceBoardTheme",mods:".prevent"}],settings:[{property:"colors.text",default:"#000000",title:"Text"},{property:"colors.background",default:"#d6daf0",title:"Background"},{property:"colors.border",default:"#b7c5d9",title:"Border"},{property:"colors.odd_row",default:"#d6daf0",title:"Odd Row"},{property:"colors.even_row",default:"#b7c5d9",title:"Even Row"},{property:"colors.playing",default:"#98bff7",title:"Playing Row"},{property:"colors.dragging",default:"#c396c8",title:"Dragging Row"},{property:"colors.controls_background",default:"#3f3f44",title:"Controls Background",description:"The controls container element background.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_background")',mods:".prevent"}]},{property:"colors.controls_inactive",default:"#FFFFFF",title:"Control Items",description:"The playback controls and played bar.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_inactive")',mods:".prevent"}]},{property:"colors.controls_active",default:"#00b6f0",title:"Focused Control Items",description:"The control items when hovered.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_active")',mods:".prevent"}]},{property:"colors.controls_empty_bar",default:"#131314",title:"Volume/Seek Bar Background",decscription:"The background of the volume and seek bars.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_empty_bar")',mods:".prevent"}]},{property:"colors.controls_loaded_bar",default:"#5a5a5b",title:"Loaded Bar Background",description:"The loaded bar within the seek bar.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_loaded_bar")',mods:".prevent"}]},{property:"colors.page_background",default:"rgb(238, 242, 255)",displayMethod:null,allowInTheme:!1}]}]},2345:e=>{e.exports=[{property:"addWebm",title:"Include WebM",description:"Whether to add all WebM files regardless of a sound filename.",default:"soundBoards",displayGroup:"Filter",options:{always:"Always",soundBoards:"Boards with sound",never:"Never"}},{property:"allow",title:"Allowed Hosts",description:"Which domains sounds are allowed to be loaded from.",default:["4cdn.org","catbox.moe","dmca.gripe","lewd.se","pomf.cat","zz.ht","zz.fo"],actions:[{title:"Reset",handler:'settings.reset("allow")',mods:".prevent"}],displayGroup:"Filter",displayMethod:"textarea",attrs:"rows=10",format:e=>e.join("\n"),parse:e=>e.split("\n")},{property:"filters",default:["# Image MD5 or sound URL"],title:"Filters",description:"List of URLs or image MD5s to filter, one per line.\nLines starting with a # will be ignored.",actions:[{title:"Reset",handler:'settings.reset("filters")',mods:".prevent"}],displayGroup:"Filter",displayMethod:"textarea",attrs:"rows=10",format:e=>e.join("\n"),parse:e=>e.split("\n")}]},8620:e=>{e.exports=[{property:"defaultUploadHost",default:"catbox",parse:"settings.hosts.setDefault"},{property:"uploadHosts",title:"Hosts",actions:[{title:"Add",handler:"settings.hosts.add",mods:".prevent"},{title:"Restore Defaults",handler:"settings.hosts.restoreDefaults",mods:".prevent"}],displayGroup:"Hosts",displayMethod:"settings.hosts.template",parse:"settings.hosts.parse",looseCompare:!0,wideDesc:!0,description:'Each host needs a unique name and URL that points to an upload endpoint.
The form data is a JSON representation of the data sent with the upload, with the file being indicated as "$file". The form data and headers allow for any other information to be sent, such as a user token.
A response path or match can optionally be provided to get a link to the uploaded file from the response. Use "Response Path" for JSON responses to set where a link or filename can be found in the response. For all other responses "Response Match" takes a regular expression (without slashes) that is applied to the result, with the first capture group being the link or filename. File URL format can be set if you only have part of the link, such as the filename. The response, or response path/match result, will be inserted in place of %s.',mix:!0,default:{catbox:{default:!0,url:"https://catbox.moe/user/api.php",data:{reqtype:"fileupload",fileToUpload:"$file",userhash:null},filenameLength:29},pomf:{url:"https://pomf.cat/upload.php",data:{"files[]":"$file"},responsePath:"files.0.url",soundUrl:"a.pomf.cat/%s",filenameLength:23},zz:{url:"https://zz.ht/api/upload",responsePath:"files.0.url",data:{"files[]":"$file"},headers:{token:null},filenameLength:19},lewd:{url:"https://lewd.se/upload",data:{file:"$file"},headers:{token:null,shortUrl:!0},responsePath:"data.link",filenameLength:30}}}]},5303:(e,t,a)=>{e.exports=[...a(1277),...a(7022),...a(2345),...a(6270),...a(5066),...a(8620),{property:"viewStyle",default:"playlist"},{property:"showPlaylistSearch",default:!0},{property:"imageHeight",default:125},{property:"offsetTop",default:"0"},{property:"offsetBottom",default:"0"}]},6270:e=>{const t="mediaSession"in navigator,a={displayGroup:"Keybinds",format:"hotkeys.stringifyKey",parse:"hotkeys.parseKey",attrs:'@keydown="settings.handleKeyChange"',property:"hotkey_bindings",allowInTheme:!0};e.exports=[{title:"Keybinds",displayGroup:"Keybinds",settings:[{property:"hotkeys",default:"open",title:"Enabled",options:{always:"Always",open:"Only with the player open",never:"Never"}},{property:"hardwareMediaKeys",title:"Hardware Media Keys",displayGroup:"Keybinds",description:"Enable playback control via hardware media keys."+(t?"":" Your browser does not support this feature."),default:t,attrs:!t&&"disabled"}]},{title:"Playback",themeFieldTitle:"Playback Keybinds",...a,settings:[{property:"hotkey_bindings.playPause",title:"Play/Pause",keyHandler:"togglePlay",ignoreRepeat:!0,default:{key:" "}},{property:"hotkey_bindings.previous",title:"Previous",keyHandler:()=>Player.previous({force:!0}),ignoreRepeat:!0,default:{key:"arrowleft"}},{property:"hotkey_bindings.next",title:"Next",keyHandler:()=>Player.next({force:!0}),ignoreRepeat:!0,default:{key:"arrowright"}},{property:"hotkey_bindings.previousGroup",title:"Previous Group",keyHandler:()=>Player.previous({force:!0,group:!0}),ignoreRepeat:!0,default:{shiftKey:!0,key:"arrowleft"}},{property:"hotkey_bindings.nextGroup",title:"Next Group",keyHandler:()=>Player.next({force:!0,group:!0}),ignoreRepeat:!0,default:{shiftKey:!0,key:"arrowright"}},{property:"hotkey_bindings.volumeUp",title:"Volume Up",keyHandler:"actions.volumeUp",default:{shiftKey:!0,key:"arrowup"}},{property:"hotkey_bindings.volumeDown",title:"Volume Down",keyHandler:"actions.volumeDown",default:{shiftKey:!0,key:"arrowdown"}},{property:"hotkey_bindings.shuffle",title:"Shuffle",keyHandler:"playlist.toggleShuffle",default:{key:""}},{property:"hotkey_bindings.repeat",title:"Toggle Repeat",keyHandler:"playlist.toggleRepeat",default:{key:""}}]},{title:"Display",themeFieldTitle:"Display Keybinds",...a,settings:[{property:"hotkey_bindings.closePlayer",title:"Close",keyHandler:"display.close",default:{key:""}},{property:"hotkey_bindings.togglePlayer",title:"Show/Hide",keyHandler:"display.toggle",default:{key:"h"}},{property:"hotkey_bindings.toggleFullscreen",title:"Toggle Fullscreen",keyHandler:"display.toggleFullScreen",default:{key:""},allowFocusedInput:!0},{property:"hotkey_bindings.togglePlaylist",title:"Toggle Playlist",keyHandler:"playlist.toggleView",default:{key:""}},{property:"hotkey_bindings.toggleSearch",title:"Toggle Playlist Search",keyHandler:()=>Player.set("showPlaylistSearch",!Player.config.showPlaylistSearch),default:{key:""},allowFocusedInput:!0},{property:"hotkey_bindings.scrollToPlaying",title:"Jump To Playing",keyHandler:()=>Player.playlist.scrollToPlaying(),default:{key:""}},{property:"hotkey_bindings.toggleHoverImages",title:"Toggle Hover Images",keyHandler:"playlist.toggleHoverImages",default:{key:""}},{property:"hotkey_bindings.toggleAutoScroll",title:"Toggle Thread Scroll",keyHandler:()=>Player.set("autoScrollThread",!Player.config.autoScrollThread),default:{key:""}}]},{title:"Theme",themeFieldTitle:"Theme Keybinds",...a,settings:[{property:"hotkey_bindings.nextTheme",title:"Next Theme",keyHandler:"theme.next",default:{key:""}},{property:"hotkey_bindings.previousTheme",title:"Previous Theme",keyHandler:"theme.previous",default:{key:""}},{property:"hotkey_bindings.switchTheme",title:"Select Theme",keyHandler:"theme.handleSwitch",default:[],displayMethod:"theme.themeKeybindsTemplate",parse:"theme.parseSwitch",format:null}]}]},7022:e=>{e.exports=[{property:"shuffle",title:"Shuffle",displayGroup:"Playback",default:!1},{property:"repeat",title:"Repeat",displayGroup:"Playback",default:"all",options:{all:"All",one:"One",none:"None"}},{property:"preventSleep",title:"Prevent Sleep",displayGroup:"Playback",description:"Prevent sleeping while audio is playing. This only works when the browser and tab are in the foreground.",default:!0},{property:"autoplayNext",title:"Autoplay Next",displayGroup:"Playback",description:"Automatically play the next sound when the current one finishes.",default:!0},{property:"restartSeconds",title:"Restart After",displayGroup:"Playback",description:"How long into a track until selecting previous restarts the track instead. Set to 0 to disable.",default:3,parse:e=>+e>=0&&+e<1/0?+e:0},{title:"Inline Player",displayGroup:"Playback",settings:[{property:"playExpandedImages",title:"Expanded Image",description:"Play audio when sound images are expanded.",default:!0,dependentRender:["expandedControls"]},{property:"expandedControls",title:"Expanded Controls",description:"Show playback controls for expanded images.",default:!0,attrs:()=>Player.config.playExpandedImages?"":"disabled"},{property:"expandedLoopMaster",title:"Master Source",default:"sound",description:"Which media source to play in full for audio and video of different durations.",options:{sound:"Audio",video:"Video"}},{property:"expandedAllowFiltered",title:"Allow Filtered",default:!0,description:"Allow sounds that have been filtered to be played inline. Sounds from unknown hosts will not be played regardless of this setting."},{property:"expandedRepeat",title:"Repeat",default:"all",description:"How to repeat expanded images with multiple sounds.",options:{all:"All",one:"One",none:"None"}},{property:"playHoveredImages",title:"Hover Image",description:"Play audio when sound hover images are shown. This applies to hover images displayed by the native extention or 4chan X.",default:!0}]}]},5066:(e,t,a)=>{e.exports=[{property:"savedThemes",title:"Saved Themes",actions:[{title:"Restore Defaults",handler:"theme.restoreDefaults",mods:".prevent"},{title:"Save Current",handler:"theme.showSaveOptions",mods:".prevent.stop"}],displayGroup:"Theme",displayMethod:"theme.savedThemesTemplate",mix:!0,default:a(1469)},{property:"savedThemesOrder",default:[]},{property:"selectedTheme",default:"Default"},{property:"headerTemplate",title:"Header",actions:[{title:"Reset",handler:'settings.reset("headerTemplate")',mods:".prevent"}],default:"repeat-button shuffle-button hover-images-button playlist-button\nsound-title-marquee\nview-menu-button add-button theme-menu-button close-button",displayGroup:"Theme",displayMethod:"textarea",themeField:!0},{property:"rowTemplate",title:"Row",actions:[{title:"Reset",handler:'settings.reset("rowTemplate")',mods:".prevent"}],default:"sound-title h:{menu-button}",displayGroup:"Theme",displayMethod:"textarea",themeField:!0},{property:"footerTemplate",title:"Footer",actions:[{title:"Reset",handler:'settings.reset("footerTemplate")',mods:".prevent"}],default:`playing-button:"sound-index / " sound-count sounds\n\np:{\n\t\tpost-link\n\t\tOpen [ image-link sound-link ]\n\t\tDownload [ dl-image-button dl-sound-button ]\n}\n\n`,displayGroup:"Theme",displayMethod:"textarea",attrs:'rows="10"',themeField:!0},{property:"chanXTemplate",title:"4chan X Header",default:'p:{\n\tpost-link:"sound-title"\n\tprev-button\n\tplay-button\n\tnext-button\n\tsound-current-time / sound-duration\n}',actions:[{title:"Reset",handler:'settings.reset("chanXTemplate")',mods:".prevent"}],displayGroup:"Theme",displayMethod:"textarea",attrs:'rows="10"',themeField:!0},{property:"customCSS",title:"Custom CSS",default:"",displayGroup:"Theme",displayMethod:"textarea",attrs:'rows="10"',themeField:!0}]},1952:()=>{window.ns="fcsp",window.is4chan=location.hostname.includes("4chan.org")||location.hostname.includes("4channel.org"),window.isChanX=document.documentElement&&document.documentElement.classList.contains("fourchan-x"),window.isOneeChan=document.documentElement&&document.documentElement.classList.contains("oneechan"),window.Board=location.pathname.split("/")[1],window.Thread=(location.href.match(/\/thread\/(\d+)/)||[])[1],window.Site=is4chan?"4chan":((document.head.querySelector('meta[name="generator"]')||{}).content||"").includes("FoolFuuka")?"FoolFuuka":location.hostname.includes("warosu.org")?"Fuuka":"FoolFuuka";class e extends Error{constructor(e,t,a){super(e),this.reason=e,this.type=t,this.error=a}}window.PlayerError=e},5463:e=>{e.exports={catbox:{filepath:"//files.catbox.moe/",decode:!1},audio:{decode:!0},sound:{decode:!0}}},4302:(e,t,a)=>{e.exports={fcSounds:'',arrowClockwise:a(5226).A,arrowsCollapse:a(1730).A,arrowDown:a(4292).A,arrowsExpand:a(5331).A,arrowRepeat:a(8997).A,arrowUp:a(991).A,boxArrowInLeft:a(1733).A,boxArrowRight:a(6818).A,chatRightQuote:a(9908).A,checkSquare:a(188).A,chevronDown:a(6042).A,chevronUp:a(2793).A,close:a(2340).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),gear:a(2181).A,fileEarmarkImage:a(794).A,fileEarmarkMusic:a(416).A,filter:a(706).A,fullscreen:a(4855).A,fullscreenExit:a(9520).A,github:a(5737).A,image:a(187).A,infoCircle:a(2277).A,layoutTextWindow:a(8979).A,link:a(5916).A,musicNoteList:a(5763).A,play:a(1786).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),playFill:a(5540).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),pause:a(8250).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),pauseFill:a(4708).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),plus:a(6001).A,reboot:a(3264).A,search:a(8472).A,shuffle:a(2487).A,skipEnd:a(7453).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),skipEndFill:a(137).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),skipStart:a(1590).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),skipStartFill:a(1992).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),soundwave:a(8998).A,speaker:a(7119).A,square:a(6289).A,tools:a(6933).A,trash:a(2602).A,volumeMute:a(7568).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"'),volumeMuteFill:a(4250).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"'),volumeUp:a(3220).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"'),volumeUpFill:a(7654).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"')}},3980:(e,t,a)=>{var n=a(4302);e.exports=(e={})=>`
\n\t\t\t\tSelect an image and sound to combine as a sound image.\n\t\t\t\tThe sound will be uploaded to the selected file host and the url will be added to the image filename. \n\t\t\t\t \n\t\t\t\tMultiple sound files, or a comma-separated list of sound URLs, can be given for a single image.\n\t\t\t\tIf you do have multiple sounds the name will also be a considered comma-separated list. \n\t\t\t\tDismiss\n\t\t\t
`)).join(""))},handleFileRemove(e){const t=+e.currentTarget.getAttribute("data-idx"),a=e.currentTarget.closest(`.${ns}-file-input`).querySelector('input[type="file"]'),n=new DataTransfer;for(let e=0;e{const a=e.type.startsWith("video"),n=e.type.startsWith("image")||"video/webm"===e.type,s=e.type.startsWith("audio");if(a||n||s){const a="video/webm"===e.type&&t?t:n?Player.tools.imgInput:Player.tools.sndInput,s=new DataTransfer;a.multiple&&[...a.files].forEach((e=>s.items.add(e))),s.items.add(e),a.files=s.files,Player.tools.handleFileSelect(a),a===Player.tools.imgInput&&Player.tools.handleImageSelect(),a===Player.tools.sndInput&&Player.tools.useSoundURL&&Player.tools.toggleSoundInput("file")}})),!1},async handleCreate(){Player.tools._createdImageURL&&URL.revokeObjectURL(Player.tools._createdImageURL),Player.tools._createdImage=null,o.status.style.display="block",o.status.innerHTML="Creating sound image",Player.$(`.${ns}-create-button`).disabled=!0;const e=Player.config.uploadHosts[Player.$(`.${ns}-create-sound-host`).value],t=Player.tools.useSoundURL;let a=Player.tools.imgInput.files[0],s=t&&Player.$(`.${ns}-create-sound-snd-url`).value.split(",").map((e=>e.trim())).filter((e=>e)),l=(Player.$(`.${ns}-use-video`)||{}).checked&&a&&a.type.startsWith("video")?a&&[a]:[...Player.tools.sndInput.files];const i=Player.$(`.${ns}-create-sound-name`).value,d=i?((s||l).length>1?i.split(","):[i]).map((e=>e.trim())):a&&[a.name.replace(/\.[^/.]+$/,"")];try{if(!a)throw new PlayerError("Select an image or webm.","warning");if(a.type.startsWith("video")&&await Player.tools.hasAudio(a))throw o.status.innerHTML+=" Audio not allowed for the image webm. Remove the audio from the webm and try again.",new PlayerError("Audio not allowed for the image webm.","warning");const i=d.join("").length+8*(s||l).length;if(t){try{s=s.map((e=>new URL(e)&&e.replace(/^(https?:)?\/\//,"")))}catch(e){throw new PlayerError("The provided sound URL is invalid.","warning")}if(2188)throw new PlayerError("The generated image filename is too long.","warning");l=await Promise.all(l.map((async e=>{if(e.type.startsWith("video")&&!await Player.tools.hasAudio(e))throw new PlayerError(`The selected video has no audio. (${e.name})`,"warning");return e})));try{s=await Promise.all(l.map((async t=>Player.tools.postFile(t,e))))}catch(e){throw new PlayerError("Upload failed.","error",e)}}if(!s.length)throw new PlayerError("No sounds selected.","warning");let c="";for(let e=0;eFailed! "+(e instanceof PlayerError?e.reason:""),Player.logError("Failed to create sound image",e)}Player.$(`.${ns}-create-button`).disabled=!1},hasAudio:e=>!(!e.type.startsWith("audio")&&!e.type.startsWith("video"))&&new Promise(((t,a)=>{const n=URL.createObjectURL(e),s=document.createElement("video");s.addEventListener("loadeddata",(()=>{URL.revokeObjectURL(n),t(s.mozHasAudio||!!s.webkitAudioDecodedByteCount)})),s.addEventListener("error",a),s.src=n})),async postFile(e,t){const a=Player.tools._uploadIdx++;if(!t||t.invalid)throw new PlayerError("Invalid upload host.","error");const s=new FormData;return Object.keys(t.data).forEach((a=>{null!==t.data[a]&&s.append(a,"$file"===t.data[a]?e:t.data[a])})),o.status.innerHTML+=` Uploading ${e.name}`,new Promise(((r,l)=>{GM.xmlHttpRequest({method:"POST",url:t.url,data:s,responseType:t.responsePath?"json":"text",headers:t.headers,onload:async s=>{if(s.status<200||s.status>=300)return l(s);const o=t.responsePath?n.get(s.response,t.responsePath):t.responseMatch?(s.responseText.match(new RegExp(t.responseMatch))||[])[1]:s.responseText,i=(t.soundUrl?t.soundUrl.replace("%s",o):o).trim();Player.$(`.${ns}-upload-status-${a}`).innerHTML=`Uploaded ${e.name} to ${i}`,r(i)},upload:{onprogress:t=>{const n=t.total>0?t.total:e.size;Player.$(`.${ns}-upload-status-${a}`).innerHTML=`Uploading ${e.name} - ${Math.floor(t.loaded/n*100)}%`}},onerror:l})}))},addCreatedToPlayer(){Player.playlist.addFromFiles([Player.tools._createdImage])},addCreatedToQR(){if(!is4chan)return;const e=document.querySelector(isChanX?".qr-link":".open-qr-link"),t=new DataTransfer;if(t.items.add(Player.tools._createdImage),isChanX&&e){e.click();const a=new CustomEvent("drop",{view:window,bubbles:!0,cancelable:!0});a.dataTransfer=t,document.querySelector("#qr").dispatchEvent(a)}else e?(e.click(),document.querySelector("#qrFile").files=t.files):(document.querySelector("#togglePostFormLink a").click(),document.querySelector("#postFile").files=t.files,document.querySelector(".postForm").scrollIntoView())}}},6533:(e,t,a)=>{var n=a(6325);const s=a(5563),r=(e,t)=>{let a,n=new Promise(((n,s)=>{a=GM.xmlHttpRequest({method:"GET",url:e,responseType:"blob",onload:e=>n(e.response),onerror:e=>s(e),onabort:e=>{e.aborted=!0,s(e)},...t||{}})}));return t&&t.catch&&(n=n.catch(t.catch)),n.abort=a.abort,n},l=e.exports={downloadTemplate:a(4805),_downloading:null,initialize(){Player.on("rendered",l.afterRender)},afterRender(){l.resetDownloadButtons()},async _handleDownloadCancel(){Player.tools._downloading&&(Player.tools._downloadAllCanceled=!0,Player.tools._downloading.forEach((e=>e.forEach((e=>e&&e.abort())))))},async _handleDownload(e){Player.tools._downloadAllCanceled=!1,e.currentTarget.style.display="none",Player.$(`.${ns}-download-all-cancel`).style.display=null,await Player.tools.downloadThread({includeImages:Player.$(".download-all-images").checked,includeSounds:Player.$(".download-all-audio").checked,ignoreDownloaded:Player.$(".download-all-ignore-downloaded").checked,maxSounds:+Player.$(".download-all-max-sounds").value||0,concurrency:Math.max(1,+Player.$(".download-all-concurrency").value||1),compression:Math.max(0,Math.min(+Player.$(".download-all-compression").value||0,9)),status:Player.$(`.${ns}-download-all-status`)}).catch((()=>{})),Player.tools.resetDownloadButtons()},resetDownloadButtons(){Player.$(`.${ns}-download-all-start`).style.display=Player.tools._downloading?"none":null,Player.$(`.${ns}-download-all-cancel`).style.display=Player.tools._downloading?null:"none",Player.$(`.${ns}-download-all-save`).style.display=Player.tools.threadDownloadBlob?null:"none",Player.$(`.${ns}-download-all-clear`).style.display=Player.tools.threadDownloadBlob?null:"none",Player.$(`.${ns}-ignore-downloaded`).style.display=Player.sounds.some((e=>e.downloaded))?null:"none"},async download(e,t){try{const a=await r(e),s=n.element(``);s.click(),URL.revokeObjectURL(s.href)}catch(e){Player.logError("There was an error downloading.",e,"warning")}},async downloadThread({includeImages:e,includeSounds:t,ignoreDownloaded:a,maxSounds:l,concurrency:o,compression:i,status:d}){const c=new JSZip;!(l>0)&&(l=1/0);const p=Player.sounds.filter((e=>e.post&&(!a||!e.downloaded))).slice(0,l),y=p.length;if(d&&(d.style.display="block"),!y||!e&&!t)return d&&(d.innerHTML="Nothing to download.");Player.tools._downloading=[],d&&(d.innerHTML=`Downloading ${y} sound images.
\n\t\t\tThis may take a while. You can leave it running in the background, but if you background the tab your browser will slow it down.\n\t\t\tYou'll be prompted to download the zip file once complete.
`,u[0].el,"beforebegin"):(m&&c.file(`${i}${l.filename}`,m),v&&c.file(`${i}${encodeURIComponent(l.src)}`,v),l.downloaded=!0)),await a(s)}))),Player.tools._downloadAllCanceled&&n.element(`Canceled at ${h} / ${y}.`,d);const m=d&&n.element("
Generating zip file...
",d);try{const e={type:"blob",compression:i?"DEFLATE":"STORE",compressionOptions:{level:i}};Player.tools.threadDownloadBlob=await c.generateAsync(e,(e=>{d&&(m.textContent=`Generating zip file (${e.percent.toFixed(2)}%)...`)})),d&&n.element("Complete!",d),Player.tools.saveThreadDownload()}catch(e){console.error("[4chan sounds player] Failed to generate zip",e),d&&(m.textContent="Failed to generate zip file!")}Player.tools._downloading=null,Player.tools.resetDownloadButtons()},saveThreadDownload(){const e=Thread||"-",t=n.element(``);t.click(),URL.revokeObjectURL(t.href)},clearDownloadBlob(){delete Player.tools.threadDownloadBlob,Player.tools.resetDownloadButtons()}}},5305:(e,t,a)=>{var n=a(6325);const s=a(8433),r=a(6533);e.exports={template:a(2230),...s,...r,initialize(){s.initialize(),r.initialize()},render(){n.elementHTML(Player.$(`.${ns}-tools`).innerHTML,Player.tools.template()),s.afterRender(),r.afterRender()},toggle(){"tools"===Player.config.viewStyle?Player.playlist.restore():Player.display.setViewStyle("tools")},handleDecoded(e){Player.$(`.${ns}-encoded-input`).value=encodeURIComponent(e.currentTarget.value)},handleEncoded(e){Player.$(`.${ns}-decoded-input`).value=decodeURIComponent(e.currentTarget.value)}}},5535:(e,t,a)=>{var n=a(4302),s=a(6325);const{postIdPrefix:r}=a(218);e.exports=[{property:"repeat",tplName:"repeat",action:"playlist.toggleRepeat",actionMods:".prevent",values:{all:{attrs:['title="Repeat All"'],icon:n.arrowRepeat},one:{attrs:['title="Repeat One"'],icon:n.arrowClockwise},none:{attrs:['title="No Repeat"'],class:"muted",icon:n.arrowRepeat}}},{property:"shuffle",tplName:"shuffle",action:"playlist.toggleShuffle",actionMods:".prevent",values:{true:{attrs:['title="Shuffled"'],icon:n.shuffle},false:{attrs:['title="Ordered"'],class:"muted",icon:n.shuffle}}},{property:"viewStyle",tplName:"playlist",action:"playlist.toggleView",values:{default:{attrs:['title="Player"'],class:"muted",icon:()=>"playlist"===Player.playlist._lastView?n.arrowsExpand:n.arrowsCollapse},playlist:{attrs:['title="Hide Playlist"'],icon:n.arrowsExpand},image:{attrs:['title="Show Playlist"'],icon:n.arrowsCollapse}}},{property:"hoverImages",tplName:"hover-images",action:"playlist.toggleHoverImages",values:{true:{attrs:['title="Hover Images Enabled"'],icon:n.image},false:{attrs:['title="Hover Images Disabled"'],class:"muted",icon:n.image}}},{tplName:"add",action:"playlist.selectLocalFiles",actionMods:".prevent",icon:n.plus,attrs:['title="Add local files"']},{tplName:"reload",action:"posts.refresh",actionMods:".prevent",icon:n.reboot,attrs:['title="Reload the playlist"']},{property:"viewStyle",tplName:"settings",action:"settings.toggle()",actionMods:".prevent",icon:n.gear,attrs:['title="Settings"'],values:{default:{class:"muted"},settings:{}}},{property:"viewStyle",tplName:"threads",action:"threads.toggle",actionMods:".prevent",icon:n.search,attrs:['title="Threads"'],values:{default:{class:"muted"},threads:{}}},{property:"viewStyle",tplName:"tools",action:"tools.toggle",actionMods:".prevent",icon:n.tools,attrs:['title="Tools"'],values:{default:{class:"muted"},tools:{}}},{tplName:"close",action:"hide",actionMods:".prevent",icon:n.close,attrs:['title="Hide the player"']},{tplName:"playing",requireSound:!0,action:'playlist.scrollToPlaying("center")',actionMods:".prevent",icon:n.musicNoteList,attrs:['title="Scroll the playlist to the currently playing sound."']},{tplName:"post",requireSound:!0,icon:n.chatRightQuote,showIf:e=>e.sound.post,attrs:e=>["href="+("#"+r+e.sound.post),'title="Jump to the post for the current sound"']},{tplName:"image",requireSound:!0,icon:n.image,attrs:e=>[`href=${e.sound.image}`,'title="Open the image in a new tab"','target="_blank"']},{tplName:"sound",requireSound:!0,icon:n.soundwave,attrs:e=>[`href=${e.sound.src}`,'title="Open the sound in a new tab"','target="_blank"']},{tplName:/dl-(image|sound)/,requireSound:!0,action:e=>{const t=e.sound["image"===e.tplNameMatch[1]?"image":"src"],a=e.sound["image"===e.tplNameMatch[1]?"filename":"name"]||"";return`tools.download("${s.escAttr(t,!0)}", "${s.escAttr(a,!0)}")`},actionMods:".prevent",icon:e=>"image"===e.tplNameMatch[1]?n.fileEarmarkImage:n.fileEarmarkMusic,attrs:e=>[`title="${"image"===e.tplNameMatch[1]?"Download the image with the original filename":"Download the sound"}"`]},{tplName:/filter-(image|sound)/,requireSound:!0,action:e=>`playlist.addFilter("${"image"===e.tplNameMatch[1]?e.sound.imageMD5:e.sound.src.replace(/^(https?:)?\/\//,"")}")`,actionMods:".prevent",icon:n.filter,showIf:e=>"sound"===e.tplNameMatch[1]||e.sound.imageMD5,attrs:e=>[`title="Add the ${"image"===e.tplNameMatch[1]?"image MD5":"sound URL"} to the filters."`]},{tplName:"remove",requireSound:!0,action:e=>`remove("${e.sound.id}")`,icon:n.trash,attrs:e=>['title="Filter the image."',`data-id="${e.sound.id}"`]},{tplName:"menu",requireSound:!0,class:`${ns}-item-menu-button`,action:e=>`playlist.handleItemMenu($event, "${e.sound.id}")`,actionMods:".prevent.stop",icon:n.chevronDown},{tplName:"view-menu",action:'display.showMenu($event.currentTarget, "views")',actionMods:".prevent.stop",icon:n.chevronDown,attrs:['title="Switch View"']},{tplName:"theme-menu",action:'display.showMenu($event.currentTarget, "themes")',actionMods:".prevent.stop",icon:n.layoutTextWindow,attrs:['title="Switch Theme"']},{tplName:"untz",action:"display.untz",icon:n.speaker,attrs:['title="UNTZ"']}]},3722:(e,t,a)=>{var n=a(6325);const s=a(5535),r=/p: ?{([^}]*)}/g,l=/h: ?{([^}]*)}/g,o=s.map((e=>`${e.tplName.source&&e.tplName.source.replace(/\(/g,"(?:")||e.tplName}`)),i=new RegExp(`(${o.join("|")})-(?:button|link)(?:\\:"([^"]+?)")?`,"g"),d=/sound-title/g,c=/sound-title-marquee/g,p=/sound-index/g,y=/sound-count/g,u=/sound-(src|id|name|post|imageOrThumb|image|thumb|filename|imageMD5)(-esc)?/g,h=/filtered-count/g,g=/\$config\[([^\]]+)\]/g,m=[];e.exports={buttons:s,initialize(){Player.on("config",Player.userTemplate._handleConfig),Player.on("playsound",(()=>Player.userTemplate._handleEvent("playsound"))),["add","remove","order","show","hide","stop"].forEach((e=>{Player.on(e,Player.userTemplate._handleEvent.bind(null,e))}))},build(e){const t=e.outerClass||"",a=e.sound&&e.sound.title||e.defaultName;let s={...e};const o=e=>"function"==typeof e?e(s):e;let m=e.template.replace(g,((...e)=>n.get(Player.config,e[1])));if(!e.ignoreDisplayBlocks&&(m=m.replace(r,Player.playing&&Player.playing===e.sound?"$1":"").replace(l,`$1`)),!e.ignoreButtons&&(m=m.replace(i,(function(a,r,l){let i=Player.userTemplate._findButtonConf(r);if(s.tplNameMatch=i.tplNameMatch,i.requireSound&&!e.sound||i.showIf&&!i.showIf(s))return"";if(i.values){i={...i,...i.values[n.get(Player.config,i.property)]||i.values[Object.keys(i.values)[0]]}}const d=[...o(i.attrs)||[]];return d.some((e=>e.startsWith("href")))||d.push('href="javascript:;"'),(i.class||t)&&d.push(`class="${i.class||""} ${t||""}"`),i.action&&d.push(`@click${i.actionMods||""}='${o(i.action)}'`),`${l&&l.replace(/ /g," ")||o(i.icon)||o(i.text)}`}))),!e.ignoreSoundName&&(m=m.replace(c,a?`
${a}
`:"").replace(d,a?`
${a}
`:"")),!e.ignoreSoundProperties&&(m=m.replace(u,((...t)=>e.sound?t[2]?n.escAttr(e.sound[t[1]],!0):e.sound[t[1]]:"")).replace(p,e.sound?Player.sounds.indexOf(e.sound)+1:0).replace(y,Player.sounds.length).replace(h,Player.filteredSounds.length)),!e.ignoreVersion&&(m=m.replace(/%v/g,"3.5.5")),e.replacements)for(let t of Object.keys(e.replacements))m=m.replace(new RegExp(t,"g"),e.replacements[t]);return m},maintain(e,t,a=[],n=[]){m.push({component:e,property:t,...Player.userTemplate.findDependencies(t,null),alwaysRenderConfigs:a,alwaysRenderEvents:n})},findDependencies(e,t){t||(t=n.get(Player.config,e));const a=[],s=y.test(t),l=d.test(t)||u.test(t),o=p.test(t),c=r.test(t),m=h.test(t);s&&a.push("add","remove"),"rowTemplate"!==e&&(l||o||c)&&a.push("playsound","stop"),o&&a.push("order"),m&&a.push("filters-applied");const v=[];let f;for(;null!==(f=i.exec(t));)if(!f[2]){let e=Player.userTemplate._findButtonConf(f[1]);e.property&&v.push(e.property)}for(;null!==(f=g.exec(t));)v.push(f[1]);return{events:a,config:v}},_handleConfig(e,t){m.forEach((a=>{a.property===e&&(Object.assign(a,Player.userTemplate.findDependencies(e,t)),a.component.render())})),m.forEach((t=>{(t.alwaysRenderConfigs.includes(e)||t.config.includes(e))&&t.component.render()}))},_handleEvent(e){m.forEach((t=>{(t.alwaysRenderEvents.includes(e)||t.events.includes(e))&&t.component.render()}))},_findButtonConf:e=>{let t,a=s.find((a=>t=a.tplName===e?[e]:a.tplName.test&&e.match(a.tplName)));return a&&{...a,tplNameMatch:t}}}},1277:e=>{e.exports=[{property:"autoshow",default:!0,title:"Autoshow",description:"Automatically show the player when the thread contains sounds.",displayGroup:"Display"},{property:"pauseOnHide",default:!0,title:"Pause On Hide",description:"Pause the player when it's hidden.",displayGroup:"Display",allowInTheme:!0},{property:"showUpdatedNotification",default:!0,title:"Show Update Notifications",description:"Show notifications when the player is successfully updated.",displayGroup:"Display"},{property:"hoverImages",title:"Hover Images",default:!1,allowInTheme:!0},{title:"Controls",displayGroup:"Display",allowInTheme:!0,settings:[{property:"preventControlWrapping",title:"Prevent Wrapping",description:"Hide controls to prevent wrapping when the player is too small",default:!0},{property:"controlsHideOrder",title:"Hide Order",description:'Order controls are hidden in to prevent wrapping. Available controls are
previous
next
seek-bar
time
duration
volume
volume-button
volume-bar
and
fullscreen
.',default:["fullscreen","duration","volume-bar","seek-bar","time","previous"],displayMethod:"textarea",inlineTextarea:!0,format:e=>e.join("\n"),parse:e=>e.split(/\s+/)}]},{title:"Minimised Display",description:"Optional displays for when the player is minimised.",displayGroup:"Display",allowInTheme:!0,settings:[{property:"pip",title:"Thumbnail",description:"Display a fixed thumbnail of the playing sound in the bottom right of the thread.",default:!0},{property:"maxPIPWidth",title:"Max Width",description:"Maximum width for the thumbnail.",default:"150px",updateCSSVars:!0},{property:"chanXControls",title:"4chan X Header Controls",description:"Show playback controls in the 4chan X header. The display can be customised in Settings>Theme.",displayMethod:isChanX||null,default:"closed",options:{always:"Always",closed:"Only with the player closed",never:"Never"}}]},{title:"Thread",displayGroup:"Display",allowInTheme:!0,settings:[{property:"autoScrollThread",description:"Automatically scroll the thread to posts as sounds play.",title:"Auto Scroll",default:!1},{property:"limitPostWidths",description:"Limit the width of posts so they aren't hidden under the player.",title:"Limit Post Widths",default:!0},{property:"minPostWidth",title:"Minimum Width",default:"50%"}]},{property:"threadsViewStyle",title:"Threads View",description:"How threads in the threads view are listed.",settings:[{title:"Display",default:"table",options:{table:"Table",board:"Board"}}]},{title:"Colors",displayGroup:"Display",property:"colors",updateCSSVars:!0,allowInTheme:!0,class:`${ns}-colorpicker-input`,attrs:'@focusout.stop.prevent="colorpicker._updatePreview" @click="colorpicker.create"',displayMethod:({value:e,attrs:t})=>`
\n\t\t\t\t\n\t\t\t\t\n\t\t\t
`,actions:[{title:"Match Theme",handler:"theme.forceBoardTheme",mods:".prevent"}],settings:[{property:"colors.text",default:"#000000",title:"Text"},{property:"colors.background",default:"#d6daf0",title:"Background"},{property:"colors.border",default:"#b7c5d9",title:"Border"},{property:"colors.odd_row",default:"#d6daf0",title:"Odd Row"},{property:"colors.even_row",default:"#b7c5d9",title:"Even Row"},{property:"colors.playing",default:"#98bff7",title:"Playing Row"},{property:"colors.dragging",default:"#c396c8",title:"Dragging Row"},{property:"colors.controls_background",default:"#3f3f44",title:"Controls Background",description:"The controls container element background.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_background")',mods:".prevent"}]},{property:"colors.controls_inactive",default:"#FFFFFF",title:"Control Items",description:"The playback controls and played bar.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_inactive")',mods:".prevent"}]},{property:"colors.controls_active",default:"#00b6f0",title:"Focused Control Items",description:"The control items when hovered.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_active")',mods:".prevent"}]},{property:"colors.controls_empty_bar",default:"#131314",title:"Volume/Seek Bar Background",decscription:"The background of the volume and seek bars.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_empty_bar")',mods:".prevent"}]},{property:"colors.controls_loaded_bar",default:"#5a5a5b",title:"Loaded Bar Background",description:"The loaded bar within the seek bar.",actions:[{title:"Reset",handler:'settings.reset("colors.controls_loaded_bar")',mods:".prevent"}]},{property:"colors.page_background",default:"rgb(238, 242, 255)",displayMethod:null,allowInTheme:!1}]}]},2345:e=>{e.exports=[{property:"addWebm",title:"Include WebM",description:"Whether to add all WebM files regardless of a sound filename.",default:"soundBoards",displayGroup:"Filter",options:{always:"Always",soundBoards:"Boards with sound",never:"Never"}},{property:"allow",title:"Allowed Hosts",description:"Which domains sounds are allowed to be loaded from.",default:["4cdn.org","catbox.moe","dmca.gripe","lewd.se","pomf.cat","zz.ht","zz.fo"],actions:[{title:"Reset",handler:'settings.reset("allow")',mods:".prevent"}],displayGroup:"Filter",displayMethod:"textarea",attrs:"rows=10",format:e=>e.join("\n"),parse:e=>e.split("\n")},{property:"filters",default:["# Image MD5 or sound URL"],title:"Filters",description:"List of URLs or image MD5s to filter, one per line.\nLines starting with a # will be ignored.",actions:[{title:"Reset",handler:'settings.reset("filters")',mods:".prevent"}],displayGroup:"Filter",displayMethod:"textarea",attrs:"rows=10",format:e=>e.join("\n"),parse:e=>e.split("\n")}]},8620:e=>{e.exports=[{property:"defaultUploadHost",default:"catbox",parse:"settings.hosts.setDefault"},{property:"uploadHosts",title:"Hosts",actions:[{title:"Add",handler:"settings.hosts.add",mods:".prevent"},{title:"Restore Defaults",handler:"settings.hosts.restoreDefaults",mods:".prevent"}],displayGroup:"Hosts",displayMethod:"settings.hosts.template",parse:"settings.hosts.parse",looseCompare:!0,wideDesc:!0,description:'Each host needs a unique name and URL that points to an upload endpoint.
The form data is a JSON representation of the data sent with the upload, with the file being indicated as "$file". The form data and headers allow for any other information to be sent, such as a user token.
A response path or match can optionally be provided to get a link to the uploaded file from the response. Use "Response Path" for JSON responses to set where a link or filename can be found in the response. For all other responses "Response Match" takes a regular expression (without slashes) that is applied to the result, with the first capture group being the link or filename. File URL format can be set if you only have part of the link, such as the filename. The response, or response path/match result, will be inserted in place of %s.',mix:!0,default:{catbox:{default:!0,url:"https://catbox.moe/user/api.php",data:{reqtype:"fileupload",fileToUpload:"$file",userhash:null},filenameLength:29},pomf:{url:"https://pomf.cat/upload.php",data:{"files[]":"$file"},responsePath:"files.0.url",soundUrl:"a.pomf.cat/%s",filenameLength:23},zz:{url:"https://zz.ht/api/upload",responsePath:"files.0.url",data:{"files[]":"$file"},headers:{token:null},filenameLength:19},lewd:{url:"https://lewd.se/upload",data:{file:"$file"},headers:{token:null,shortUrl:!0},responsePath:"data.link",filenameLength:30}}}]},5303:(e,t,a)=>{e.exports=[...a(1277),...a(7022),...a(2345),...a(6270),...a(5066),...a(8620),{property:"viewStyle",default:"playlist"},{property:"showPlaylistSearch",default:!0},{property:"imageHeight",default:125},{property:"offsetTop",default:"0"},{property:"offsetBottom",default:"0"}]},6270:e=>{const t="mediaSession"in navigator,a={displayGroup:"Keybinds",format:"hotkeys.stringifyKey",parse:"hotkeys.parseKey",attrs:'@keydown="settings.handleKeyChange"',property:"hotkey_bindings",allowInTheme:!0};e.exports=[{title:"Keybinds",displayGroup:"Keybinds",settings:[{property:"hotkeys",default:"open",title:"Enabled",options:{always:"Always",open:"Only with the player open",never:"Never"}},{property:"hardwareMediaKeys",title:"Hardware Media Keys",displayGroup:"Keybinds",description:"Enable playback control via hardware media keys."+(t?"":" Your browser does not support this feature."),default:t,attrs:!t&&"disabled"}]},{title:"Playback",themeFieldTitle:"Playback Keybinds",...a,settings:[{property:"hotkey_bindings.playPause",title:"Play/Pause",keyHandler:"togglePlay",ignoreRepeat:!0,default:{key:" "}},{property:"hotkey_bindings.previous",title:"Previous",keyHandler:()=>Player.previous({force:!0}),ignoreRepeat:!0,default:{key:"arrowleft"}},{property:"hotkey_bindings.next",title:"Next",keyHandler:()=>Player.next({force:!0}),ignoreRepeat:!0,default:{key:"arrowright"}},{property:"hotkey_bindings.previousGroup",title:"Previous Group",keyHandler:()=>Player.previous({force:!0,group:!0}),ignoreRepeat:!0,default:{shiftKey:!0,key:"arrowleft"}},{property:"hotkey_bindings.nextGroup",title:"Next Group",keyHandler:()=>Player.next({force:!0,group:!0}),ignoreRepeat:!0,default:{shiftKey:!0,key:"arrowright"}},{property:"hotkey_bindings.volumeUp",title:"Volume Up",keyHandler:"actions.volumeUp",default:{shiftKey:!0,key:"arrowup"}},{property:"hotkey_bindings.volumeDown",title:"Volume Down",keyHandler:"actions.volumeDown",default:{shiftKey:!0,key:"arrowdown"}},{property:"hotkey_bindings.shuffle",title:"Shuffle",keyHandler:"playlist.toggleShuffle",default:{key:""}},{property:"hotkey_bindings.repeat",title:"Toggle Repeat",keyHandler:"playlist.toggleRepeat",default:{key:""}}]},{title:"Display",themeFieldTitle:"Display Keybinds",...a,settings:[{property:"hotkey_bindings.closePlayer",title:"Close",keyHandler:"display.close",default:{key:""}},{property:"hotkey_bindings.togglePlayer",title:"Show/Hide",keyHandler:"display.toggle",default:{key:"h"}},{property:"hotkey_bindings.toggleFullscreen",title:"Toggle Fullscreen",keyHandler:"display.toggleFullScreen",default:{key:""},allowFocusedInput:!0},{property:"hotkey_bindings.togglePlaylist",title:"Toggle Playlist",keyHandler:"playlist.toggleView",default:{key:""}},{property:"hotkey_bindings.toggleSearch",title:"Toggle Playlist Search",keyHandler:()=>Player.set("showPlaylistSearch",!Player.config.showPlaylistSearch),default:{key:""},allowFocusedInput:!0},{property:"hotkey_bindings.scrollToPlaying",title:"Jump To Playing",keyHandler:()=>Player.playlist.scrollToPlaying(),default:{key:""}},{property:"hotkey_bindings.toggleHoverImages",title:"Toggle Hover Images",keyHandler:"playlist.toggleHoverImages",default:{key:""}},{property:"hotkey_bindings.toggleAutoScroll",title:"Toggle Thread Scroll",keyHandler:()=>Player.set("autoScrollThread",!Player.config.autoScrollThread),default:{key:""}}]},{title:"Theme",themeFieldTitle:"Theme Keybinds",...a,settings:[{property:"hotkey_bindings.nextTheme",title:"Next Theme",keyHandler:"theme.next",default:{key:""}},{property:"hotkey_bindings.previousTheme",title:"Previous Theme",keyHandler:"theme.previous",default:{key:""}},{property:"hotkey_bindings.switchTheme",title:"Select Theme",keyHandler:"theme.handleSwitch",default:[],displayMethod:"theme.themeKeybindsTemplate",parse:"theme.parseSwitch",format:null}]}]},7022:e=>{e.exports=[{property:"shuffle",title:"Shuffle",displayGroup:"Playback",default:!1},{property:"repeat",title:"Repeat",displayGroup:"Playback",default:"all",options:{all:"All",one:"One",none:"None"}},{property:"preventSleep",title:"Prevent Sleep",displayGroup:"Playback",description:"Prevent sleeping while audio is playing. This only works when the browser and tab are in the foreground.",default:!0},{property:"autoplayNext",title:"Autoplay Next",displayGroup:"Playback",description:"Automatically play the next sound when the current one finishes.",default:!0},{property:"restartSeconds",title:"Restart After",displayGroup:"Playback",description:"How long into a track until selecting previous restarts the track instead. Set to 0 to disable.",default:3,parse:e=>+e>=0&&+e<1/0?+e:0},{title:"Inline Player",displayGroup:"Playback",settings:[{property:"playExpandedImages",title:"Expanded Image",description:"Play audio when sound images are expanded.",default:!0,dependentRender:["expandedControls"]},{property:"expandedControls",title:"Expanded Controls",description:"Show playback controls for expanded images.",default:!0,attrs:()=>Player.config.playExpandedImages?"":"disabled"},{property:"expandedLoopMaster",title:"Master Source",default:"sound",description:"Which media source to play in full for audio and video of different durations.",options:{sound:"Audio",video:"Video"}},{property:"expandedAllowFiltered",title:"Allow Filtered",default:!0,description:"Allow sounds that have been filtered to be played inline. Sounds from unknown hosts will not be played regardless of this setting."},{property:"expandedRepeat",title:"Repeat",default:"all",description:"How to repeat expanded images with multiple sounds.",options:{all:"All",one:"One",none:"None"}},{property:"playHoveredImages",title:"Hover Image",description:"Play audio when sound hover images are shown. This applies to hover images displayed by the native extention or 4chan X.",default:!0}]}]},5066:(e,t,a)=>{e.exports=[{property:"savedThemes",title:"Saved Themes",actions:[{title:"Restore Defaults",handler:"theme.restoreDefaults",mods:".prevent"},{title:"Save Current",handler:"theme.showSaveOptions",mods:".prevent.stop"}],displayGroup:"Theme",displayMethod:"theme.savedThemesTemplate",mix:!0,default:a(1469)},{property:"savedThemesOrder",default:[]},{property:"selectedTheme",default:"Default"},{property:"headerTemplate",title:"Header",actions:[{title:"Reset",handler:'settings.reset("headerTemplate")',mods:".prevent"}],default:"repeat-button shuffle-button hover-images-button playlist-button\nsound-title-marquee\nview-menu-button add-button theme-menu-button close-button",displayGroup:"Theme",displayMethod:"textarea",themeField:!0},{property:"rowTemplate",title:"Row",actions:[{title:"Reset",handler:'settings.reset("rowTemplate")',mods:".prevent"}],default:"sound-title h:{menu-button}",displayGroup:"Theme",displayMethod:"textarea",themeField:!0},{property:"footerTemplate",title:"Footer",actions:[{title:"Reset",handler:'settings.reset("footerTemplate")',mods:".prevent"}],default:`playing-button:"sound-index / " sound-count sounds\n\np:{\n\t\tpost-link\n\t\tOpen [ image-link sound-link ]\n\t\tDownload [ dl-image-button dl-sound-button ]\n}\n\n`,displayGroup:"Theme",displayMethod:"textarea",attrs:'rows="10"',themeField:!0},{property:"chanXTemplate",title:"4chan X Header",default:'p:{\n\tpost-link:"sound-title"\n\tprev-button\n\tplay-button\n\tnext-button\n\tsound-current-time / sound-duration\n}',actions:[{title:"Reset",handler:'settings.reset("chanXTemplate")',mods:".prevent"}],displayGroup:"Theme",displayMethod:"textarea",attrs:'rows="10"',themeField:!0},{property:"customCSS",title:"Custom CSS",default:"",displayGroup:"Theme",displayMethod:"textarea",attrs:'rows="10"',themeField:!0}]},1952:()=>{window.ns="fcsp",window.is4chan=location.hostname.includes("4chan.org")||location.hostname.includes("4channel.org"),window.isChanX=document.documentElement&&document.documentElement.classList.contains("fourchan-x"),window.isChanXT=document.documentElement&&document.documentElement.classList.contains("fourchan-xt"),window.isOneeChan=document.documentElement&&document.documentElement.classList.contains("oneechan"),window.Board=location.pathname.split("/")[1],window.Thread=(location.href.match(/\/thread\/(\d+)/)||[])[1],window.Site=is4chan?"4chan":((document.head.querySelector('meta[name="generator"]')||{}).content||"").includes("FoolFuuka")?"FoolFuuka":location.hostname.includes("warosu.org")?"Fuuka":"FoolFuuka";class e extends Error{constructor(e,t,a){super(e),this.reason=e,this.type=t,this.error=a}}window.PlayerError=e},5463:e=>{e.exports={catbox:{filepath:"//files.catbox.moe/",decode:!1},audio:{decode:!0},sound:{decode:!0}}},4302:(e,t,a)=>{e.exports={fcSounds:'',arrowClockwise:a(5226).A,arrowsCollapse:a(1730).A,arrowDown:a(4292).A,arrowsExpand:a(5331).A,arrowRepeat:a(8997).A,arrowUp:a(991).A,boxArrowInLeft:a(1733).A,boxArrowRight:a(6818).A,chatRightQuote:a(9908).A,checkSquare:a(188).A,chevronDown:a(6042).A,chevronUp:a(2793).A,close:a(2340).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),gear:a(2181).A,fileEarmarkImage:a(794).A,fileEarmarkMusic:a(416).A,filter:a(706).A,fullscreen:a(4855).A,fullscreenExit:a(9520).A,github:a(5737).A,image:a(187).A,infoCircle:a(2277).A,layoutTextWindow:a(8979).A,link:a(5916).A,musicNoteList:a(5763).A,play:a(1786).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),playFill:a(5540).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),pause:a(8250).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),pauseFill:a(4708).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),plus:a(6001).A,reboot:a(3264).A,search:a(8472).A,shuffle:a(2487).A,skipEnd:a(7453).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),skipEndFill:a(137).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),skipStart:a(1590).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),skipStartFill:a(1992).A.replace(/viewBox="[^"]+"/,'viewBox="2 2 12 12"'),soundwave:a(8998).A,speaker:a(7119).A,square:a(6289).A,tools:a(6933).A,trash:a(2602).A,volumeMute:a(7568).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"'),volumeMuteFill:a(4250).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"'),volumeUp:a(3220).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"'),volumeUpFill:a(7654).A.replace(/viewBox="[^"]+"/,'viewBox="1 1 14 14"')}},3980:(e,t,a)=>{var n=a(4302);e.exports=(e={})=>`
\n\t\t\t\tSelect an image and sound to combine as a sound image.\n\t\t\t\tThe sound will be uploaded to the selected file host and the url will be added to the image filename. \n\t\t\t\t \n\t\t\t\tMultiple sound files, or a comma-separated list of sound URLs, can be given for a single image.\n\t\t\t\tIf you do have multiple sounds the name will also be a considered comma-separated list. \n\t\t\t\tDismiss\n\t\t\t