//META{"name":"ThemeRepo","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ThemeRepo","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ThemeRepo/ThemeRepo.plugin.js"}*// class ThemeRepo { getName () {return "ThemeRepo";} getVersion () {return "1.8.1";} getAuthor () {return "DevilBro";} getDescription () {return "Allows you to preview all themes from the theme repo and download them on the fly. Repo button is in the theme settings.";} initConstructor () { this.changelog = { "fixed":[["Canary/PTB","Fixed the plugin for canary and ptb"]] }; this.patchModules = { "V2C_List":"componentDidMount" }; this.sortings = { sort: { name: "Name", author: "Author", version: "Version", description: "Description", state: "Update State", fav: "Favorites", new: "New Themes" }, order: { asc: "Ascending", desc: "Descending" } }; this.loading = {is:false, timeout:null, amount:0}; this.cachedThemes = []; this.grabbedThemes = []; this.foundThemes = []; this.loadedThemes = {}; this.updateInterval; this.themeFixerCSS = `${BDFDB.dotCNC.appmount + BDFDB.dotCNC.appcontainer + BDFDB.dotCNC.channelheaderheaderbar + BDFDB.dotCNC.channelheadertitle + BDFDB.dotCNC.guildchannels + BDFDB.dotCNC.channels + BDFDB.dotCNC.callcurrentcontainer + BDFDB.dotCNC.callcurrentvideo + BDFDB.dotCNC.callcurrentdetails + BDFDB.dotCNC.accountinfo + BDFDB.dotCNC.nochannel + BDFDB.dotCNC.friends + BDFDB.dotCNC.friendstable + BDFDB.dotCNC.friendstableheader + BDFDB.dotCNC.guilds + BDFDB.dotCNC.guildswrapper + BDFDB.dotCNC.channelheadertitle + BDFDB.dotCNC.typing + BDFDB.dotCNS.emojipicker + BDFDB.dotCNS.emojipickerscroller + BDFDB.dotCN.emojipickeremojiitem + BDFDB.dotCNC.emojipickerselected + BDFDB.dotCNC.members + BDFDB.dotCNC.chat + BDFDB.dotCNS.chat + "form," + BDFDB.dotCNC.chatcontent + BDFDB.dotCNC.messageswrapper + BDFDB.dotCNC.searchresultswrap + BDFDB.dotCNC.searchresultschannelname + BDFDB.dotCNC.searchresultssearchheader + BDFDB.dotCNC.activityfeed + BDFDB.dotCNC.lfg + BDFDB.dotCNC.applicationstore + BDFDB.dotCNC.giftinventory + BDFDB.dotCNC.gamelibrary + BDFDB.dotCNC.gamelibrarytableheader + BDFDB.dotCNC.standardsidebarview + BDFDB.dotCNC.sidebarregion + BDFDB.dotCNC.contentregion + BDFDB.dotCN.scroller} {background: transparent !important;} ${BDFDB.dotCNC.layer + BDFDB.dotCNC.layers + BDFDB.dotCN.titlebar} {background: rgba(0,0,0,0.18) !important;} ${BDFDB.dotCN.card}:not([style*="background-color"]) {background: rgba(0,0,0,0.4) !important;}`; this.themeRepoButtonMarkup = ``; this.settingsContextEntryMarkup = `
Theme Repo
`; this.themeRepoLoadingIconMarkup = ` `; this.frameMarkup = ``; this.themeEntryMarkup = `
  • v by
  • `; this.themeRepoModalMarkup = `

    Theme Repository

    Themes
    Settings
    Sort by:
    ${this.sortings.sort[Object.keys(this.sortings.sort)[0]]}
    Order:
    ${this.sortings.order[Object.keys(this.sortings.order)[0]]}

      You can toggle this menu with the "Ctrl" key to take a better look at the preview.

      Preview in light mode

      Preview with normalized classes

      Include Custom CSS in Preview

      Include ThemeFixer CSS in Preview

      Download ThemeFixer

      Hide updated Themes.

      Hide outdated Themes.

      Hide downloadable Themes.

      Apply Theme after Download (Automatic loading enabled)

      `; this.sortPopoutMarkup = `
      ${Object.keys(this.sortings.sort).map((key, i) => `
      ${this.sortings.sort[key]}
      `).join("")}
      `; this.orderPopoutMarkup = `
      ${Object.keys(this.sortings.order).map((key, i) => `
      ${this.sortings.order[key]}
      `).join("")}
      `; this.defaults = { settings: { notifyOutdated: {value:true, description:"Notifies you when one of your Themes is outdated."}, notifyNewentries: {value:true, description:"Notifies you when there are new entries in the Repo."} } }; this.css = ` ${BDFDB.dotCN.app} > .repo-loadingwrapper { position: absolute; bottom: 0; right: 0; z-index: 1000; animation: repo-loadingwrapper-fade 3s infinite ease; } @keyframes repo-loadingwrapper-fade { from {opacity: 0.1;} 50% {opacity: 0.9;} to {opacity: 0.1;} } iframe.discordPreview { width: 100vw !important; height: 100vh !important; position: absolute !important; z-index: 999 !important; } iframe.discordPreview ~ ${BDFDB.dotCN.appmount} { position: absolute !important; top: 0 !important; } iframe.discordPreview ~ ${BDFDB.dotCNS.appmount + BDFDB.dotCN.titlebar}, iframe.discordPreview ~ ${BDFDB.dotCNS.appmount + BDFDB.dotCN.app} { opacity: 0 !important; visibility: hidden !important; } .${this.name}-modal.Repo-modal ${BDFDB.dotCN.modalinner} { min-height: 100%; min-width: 800px; width: 50%; } .${this.name}-modal .themeEntry ${BDFDB.dotCN._repocontrols} > * { margin-right: 5px !important; } .${this.name}-modal .themeEntry ${BDFDB.dotCN._repocontrols} > .previewCheckboxWrapper { margin-right: 0px !important; } .${this.name}-modal .themeEntry svg[fill="currentColor"], .${this.name}-modal .themeEntry ${BDFDB.dotCN.giffavoritebutton} { cursor: pointer; } .${this.name}-modal .themeEntry svg[fill="currentColor"], .${this.name}-modal .themeEntry ${BDFDB.dotCN.giffavoritebutton + BDFDB.notCN.giffavoriteselected} { color: #72767d !important; } ${BDFDB.dotCN.themedark} .${this.name}-modal .themeEntry svg[fill="currentColor"], ${BDFDB.dotCN.themedark} .${this.name}-modal .themeEntry ${BDFDB.dotCN.giffavoritebutton + BDFDB.notCN.giffavoriteselected} { color: #dcddde !important; } .${this.name}-modal .themeEntry.downloadable .trashIcon { opacity: 0 !important; pointer-events: none !important; }`; } getSettingsPanel () { if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return; var settings = BDFDB.getAllData(this, "settings"); var settingshtml = `
      ${this.name}
      `; for (let key in settings) { settingshtml += `

      ${this.defaults.settings[key].description}

      `; } settingshtml += `

      Add Theme:

      `; settingshtml += `

      Your additional Theme List:

      `; var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; if (ownlist) for (let url of ownlist) { settingshtml += `
      ${url}
      `; } settingshtml += `
      `; settingshtml += `

      Force all Themes to be fetched again.

      `; settingshtml += `

      Remove all added Themes from your own list.

      `; settingshtml += `
      `; let settingspanel = BDFDB.htmlToElement(settingshtml); BDFDB.initElements(settingspanel, this); BDFDB.addEventListener(this, settingspanel, "click", ".btn-addtheme", () => {this.addThemeToOwnList(settingspanel);}); BDFDB.addEventListener(this, settingspanel, "click", "#input-themeurl", e => {if (e.which == 13) this.addThemeToOwnList(settingspanel);}); BDFDB.addEventListener(this, settingspanel, "click", ".remove-theme", e => {this.removeThemeFromOwnList(e);}); BDFDB.addEventListener(this, settingspanel, "click", ".remove-all", () => {this.removeAllFromOwnList(settingspanel);}) BDFDB.addEventListener(this, settingspanel, "click", ".refresh-button", () => { this.loading = {is:false, timeout:null, amount:0}; this.loadThemes(); }); return settingspanel; } //legacy load () {} start () { if (!global.BDFDB) global.BDFDB = {myPlugins:{}}; if (global.BDFDB && global.BDFDB.myPlugins && typeof global.BDFDB.myPlugins == "object") global.BDFDB.myPlugins[this.getName()] = this; var libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]'); if (!libraryScript || performance.now() - libraryScript.getAttribute("date") > 600000) { if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"); libraryScript.setAttribute("date", performance.now()); libraryScript.addEventListener("load", () => {if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize();}); document.head.appendChild(libraryScript); } else if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize(); this.startTimeout = setTimeout(() => {this.initialize();}, 30000); } initialize () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { if (this.started) return; BDFDB.loadMessage(this); this.loadThemes(); this.updateInterval = setInterval(() => {this.checkForNewThemes();},1000*60*30); BDFDB.WebModules.forceAllUpdates(this); } else { console.error(`%c[${this.getName()}]%c`, 'color: #3a71c1; font-weight: 700;', '', 'Fatal Error: Could not load BD functions!'); } } stop () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { clearInterval(this.updateInterval); clearTimeout(this.loading.timeout); BDFDB.removeEles("iframe.discordPreview",".themerepo-notice",".bd-themerepobutton",".themerepo-loadingicon",BDFDB.dotCN.app + " > .repo-loadingwrapper:empty"); BDFDB.unloadMessage(this); } } // begin of own functions onUserSettingsCogContextMenu (instance, menu) { let observer = new MutationObserver(changes => { changes.forEach(change => { if (change.addedNodes) change.addedNodes.forEach(node => { if (node.tagName && BDFDB.containsClass(node, BDFDB.disCN.contextmenu) && BDFDB.getReactValue(node, "return.return.return.memoizedProps.label") == "BandagedBD" && !node.querySelector(".themerepo-item")) { let item = node.querySelectorAll(BDFDB.dotCN.contextmenuitem); item = item[item.length-1]; var settingsContextEntry = BDFDB.htmlToElement(this.settingsContextEntryMarkup); settingsContextEntry.addEventListener("click", () => { if (!this.loading.is) BDFDB.closeContextMenu(menu); this.openThemeRepoModal(); }); item.parentElement.insertBefore(settingsContextEntry, item.nextElementSibling); var menurects = BDFDB.getRects(menu); node.style.setProperty("top", (menurects.top - BDFDB.getRects(node).height + menurects.height) + "px"); } }); }); }); observer.observe(menu, {childList: true, subtree:true}); } processV2CList (instance, wrapper) { if (!document.querySelector(".bd-themerepobutton") && window.PluginUpdates && window.PluginUpdates.plugins && instance._reactInternalFiber.key && instance._reactInternalFiber.key.split("-")[0] == "theme") { var folderbutton = document.querySelector(BDFDB.dotCN._repofolderbutton); if (folderbutton) { var repoButton = BDFDB.htmlToElement(``); repoButton.addEventListener("click", () => { this.openThemeRepoModal() }); repoButton.addEventListener("mouseenter", () => { BDFDB.createTooltip("Open Theme Repo", repoButton, {type:"top",selector:"themerepo-button-tooltip"}); }); folderbutton.parentElement.insertBefore(repoButton, folderbutton.nextSibling); } } }; addThemeToOwnList (settingspanel) { var themeUrlInput = settingspanel.querySelector("#input-themeurl"); var themeList = settingspanel.querySelector(".theme-list"); if (themeUrlInput && themeList) { var url = themeUrlInput.value; themeUrlInput.value = null; var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; if (!ownlist.includes(url)) { ownlist.push(url); BDFDB.saveData("ownlist", ownlist, this, "ownlist"); let entry = BDFDB.htmlToElement(`
      ${url}
      `) BDFDB.addChildEventListener(entry, "click", ".remove-theme", e => {this.removeThemeFromOwnList(e);}); themeList.appendChild(entry); } } } removeThemeFromOwnList (e) { var entry = e.currentTarget.parentElement; var url = entry.querySelector(".entryurl").textContent; entry.remove(); var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; BDFDB.removeFromArray(ownlist, url); BDFDB.saveData("ownlist", ownlist, this, "ownlist"); } removeAllFromOwnList (settingspanel) { BDFDB.openConfirmModal(this, "Are you sure you want to remove all added Themes from your own list?", () => { BDFDB.saveData("ownlist", [], this, "ownlist"); BDFDB.removeEles(settingspanel.querySelector(BDFDB.dotCN.hovercard)); }); } openThemeRepoModal (options = {}) { if (this.loading.is) { BDFDB.showToast(`Themes are still being fetched. Try again in some seconds.`, {type:"danger"}); return; } var keyPressed = e => { if (e.which == 17 && themeRepoModal.querySelector(BDFDB.dotCN.searchbarinput) != document.activeElement) BDFDB.toggleEles(themeRepoModal); if (e.which == 27) frame.remove(); }; var messageReceived = e => { if (typeof e.data === "object" && e.data.origin == "DiscordPreview") { switch (e.data.reason) { case "OnLoad": var username = BDFDB.myData.username; var id = BDFDB.myData.id; var discriminator = BDFDB.myData.discriminator; var avatar = BDFDB.getUserAvatar(); var nativecss = document.querySelector("head link[rel='stylesheet'][integrity]"); nativecss = nativecss && nativecss.href ? nativecss.href : null; frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"OnLoad",username,id,discriminator,avatar,nativecss},"*"); frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:darklightinput.checked,light:BDFDB.disCN.themelight,dark:BDFDB.disCN.themedark},"*"); frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"Normalize",checked:normalizeinput.checked},"*"); break; case "KeyUp": keyPressed(e.data); break; } } }; document.addEventListener("keyup", keyPressed); window.addEventListener("message", messageReceived); var frame = BDFDB.htmlToElement(this.frameMarkup); var themeRepoModal = BDFDB.htmlToElement(this.themeRepoModalMarkup); var tabbar = themeRepoModal.querySelector(BDFDB.dotCN.tabbar); tabbar.parentElement.insertBefore(BDFDB.createSearchBar("small"), tabbar.nextElementSibling); var hiddenSettings = BDFDB.loadAllData(this, "hidden"); var darklightinput = themeRepoModal.querySelector("#input-darklight"); var normalizeinput = themeRepoModal.querySelector("#input-normalize"); var customcssinput = themeRepoModal.querySelector("#input-customcss"); var themefixerinput = themeRepoModal.querySelector("#input-themefixer"); darklightinput.checked = BDFDB.getDiscordTheme() == BDFDB.disCN.themelight; normalizeinput.checked = settingsCookie["fork-ps-4"] == true; customcssinput.checked = false; themefixerinput.checked = false; themeRepoModal.querySelector("#input-hideupdated").checked = hiddenSettings.updated || options.showOnlyOutdated; themeRepoModal.querySelector("#input-hideoutdated").checked = hiddenSettings.outdated && !options.showOnlyOutdated; themeRepoModal.querySelector("#input-hidedownloadable").checked = hiddenSettings.downloadable || options.showOnlyOutdated; if (!BDFDB.isRestartNoMoreEnabled()) themeRepoModal.querySelector("#RNMoption").remove(); else themeRepoModal.querySelector("#input-rnmstart").checked = BDFDB.loadData("RNMstart", this, "RNMstart"); if (options.forcedSort && this.sortings.sort[options.forcedSort]) { var sortinput = themeRepoModal.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue); sortinput.innerText = this.sortings.sort[options.forcedSort]; sortinput.setAttribute('option', options.forcedSort); } if (options.forcedOrder && this.sortings.order[options.forcedOrder]) { var orderinput = themeRepoModal.querySelector(".order-filter " + BDFDB.dotCN.quickselectvalue); orderinput.innerText = this.sortings.order[options.forcedOrder]; orderinput.setAttribute('option', options.forcedOrder); } darklightinput.addEventListener("change", e => { frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:darklightinput.checked,light:BDFDB.disCN.themelight,dark:BDFDB.disCN.themedark},"*"); }); normalizeinput.addEventListener("change", e => { frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"Normalize",checked:normalizeinput.checked},"*"); }); customcssinput.addEventListener("change", e => { var customCSS = document.querySelector("style#customcss"); if (customCSS && customCSS.innerText.length > 0) frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"CustomCSS",checked:customcssinput.checked,css:customCSS.innerText},"*"); }); themefixerinput.addEventListener("change", e => { frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"ThemeFixer",checked:themefixerinput.checked,css:this.themeFixerCSS},"*"); }); themeRepoModal.querySelector("#download-themefixer").addEventListener("click", e => { this.createThemeFile("ThemeFixer.theme.css", `//META{"name":"ThemeFixer","description":"ThemeFixerCSS for transparent themes","author":"DevilBro","version":"1.0.1"}*//\n\n` + this.themeFixerCSS); }); BDFDB.addChildEventListener(themeRepoModal, "click", BDFDB.dotCNC.modalclose + BDFDB.dotCN.backdrop, () => { frame.remove(); document.removeEventListener("keyup", keyPressed); window.removeEventListener("message", messageReceived); }); BDFDB.addChildEventListener(themeRepoModal, "keyup", BDFDB.dotCN.searchbarinput, () => { clearTimeout(themeRepoModal.searchTimeout); themeRepoModal.searchTimeout = setTimeout(() => {this.sortEntries(themeRepoModal);},1000); }); BDFDB.addChildEventListener(themeRepoModal, "click", BDFDB.dotCN.searchbarclear, () => { clearTimeout(themeRepoModal.searchTimeout); themeRepoModal.searchTimeout = setTimeout(() => {this.sortEntries(themeRepoModal);},1000); }); BDFDB.addChildEventListener(themeRepoModal, "change", ".hide-checkbox", e => { themeRepoModal.updateHidden = true; BDFDB.saveData(e.currentTarget.value, e.currentTarget.checked, this, "hidden"); }); BDFDB.addChildEventListener(themeRepoModal, "change", "#input-rnmstart", e => { BDFDB.saveData("RNMstart", e.currentTarget.checked, this, "RNMstart"); }); BDFDB.addChildEventListener(themeRepoModal, "click", ".sort-filter", e => { BDFDB.createSortPopout(e.currentTarget, this.sortPopoutMarkup, () => {this.sortEntries(themeRepoModal);}); }); BDFDB.addChildEventListener(themeRepoModal, "click", ".order-filter", e => { BDFDB.createSortPopout(e.currentTarget, this.orderPopoutMarkup, () => {this.sortEntries(themeRepoModal);}); }); BDFDB.addChildEventListener(themeRepoModal, "click", BDFDB.dotCN.tabbaritem + "[tab=themes]", e => { if (!BDFDB.containsClass(e.currentTarget, BDFDB.disCN.settingsitemselected)) { if (themeRepoModal.updateHidden) { delete themeRepoModal.updateHidden; this.sortEntries(themeRepoModal); } } }); let favorites = BDFDB.loadAllData(this, "favorites"); let container = themeRepoModal.querySelector(".themes"); themeRepoModal.entries = {}; for (let url in this.loadedThemes) { let theme = this.loadedThemes[url]; let instTheme = window.bdthemes[this.loadedThemes[url].name]; if (instTheme && instTheme.author.toUpperCase() == theme.author.toUpperCase()) theme.state = instTheme.version != theme.version ? 1 : 0; else theme.state = 2; let data = { url: theme.url, search: (theme.name + " " + theme.version + " " + theme.author + " " + theme.description).toUpperCase(), name: theme.name, version: theme.version, author: theme.author, description: theme.description, fav: favorites[url] ? 0 : 1, new: !this.cachedThemes.includes(url) ? 0 : 1, state: theme.state, css: theme.css }; themeRepoModal.entries[url] = data; this.addEntry(frame, themeRepoModal, container, data); } this.sortEntries(themeRepoModal); BDFDB.appendModal(themeRepoModal); document.body.insertBefore(frame, document.body.firstElementChild); themeRepoModal.querySelector(BDFDB.dotCN.searchbarinput).focus(); } addEntry (frame, themeRepoModal, container, data) { if (!frame || !themeRepoModal || !container || !data) return; let entry = BDFDB.htmlToElement(this.themeEntryMarkup); setEntryState(data.state); entry.setAttribute("data-name", data.name); entry.setAttribute("data-version", data.version); entry.setAttribute("data-url", data.url); entry.querySelector(BDFDB.dotCN._reponame).innerHTML = data.name; entry.querySelector(BDFDB.dotCN._repoversion).innerHTML = data.version; entry.querySelector(BDFDB.dotCN._repoauthor).innerHTML = data.author; entry.querySelector(BDFDB.dotCN._repodescription).innerHTML = data.description; if (data.new == 0) entry.querySelector(BDFDB.dotCN._repoheadertitle).appendChild(BDFDB.htmlToElement(`NEW`)); let favbutton = entry.querySelector(BDFDB.dotCN.giffavoritebutton); BDFDB.toggleClass(favbutton, BDFDB.disCN.giffavoriteselected, data.fav == 0); favbutton.addEventListener("click", e => { let favorize = data.fav == 1; data.fav = favorize ? 0 : 1; if (favorize) BDFDB.saveData(data.url, true, this, "favorites"); else BDFDB.removeData(data.url, this, "favorites"); themeRepoModal.entries[data.url] = data; }); favbutton.addEventListener("mouseenter", e => { BDFDB.createTooltip("Favorize", favbutton, {type:"top",selector:"themerepo-favicon-tooltip"}); }); let gitbutton = entry.querySelector(".gitIcon"); gitbutton.addEventListener("click", e => { var giturl = null; if (data.url.indexOf("https://raw.githubusercontent.com") == 0) { var temp = data.url.replace("//raw.githubusercontent", "//github").split("/"); temp.splice(5, 0, "blob"); giturl = temp.join("/"); } else if (data.url.indexOf("https://gist.githubusercontent.com/") == 0) { giturl = data.url.replace("//gist.githubusercontent", "//gist.github").split("/raw/")[0]; } if (giturl) window.open(giturl, "_blank"); }); gitbutton.addEventListener("mouseenter", e => { BDFDB.createTooltip("Go to Git", gitbutton, {type:"top",selector:"themerepo-giticon-tooltip"}); }); let trashbutton = entry.querySelector(".trashIcon"); trashbutton.addEventListener("click", e => { if (BDFDB.containsClass(entry, "outdated", "updated", false)) { setEntryState(2); this.deleteThemeFile(data); if (!BDFDB.isRestartNoMoreEnabled()) this.removeTheme(data); } }); trashbutton.addEventListener("mouseenter", e => { BDFDB.createTooltip("Delete Themefile", trashbutton, {type:"top",selector:"themerepo-trashicon-tooltip"}); }); entry.querySelector(".btn-download").addEventListener("click", e => { setEntryState(0); this.downloadTheme(data); if (themeRepoModal.querySelector("#input-rnmstart").checked) setTimeout(() => {this.applyTheme(data);},3000); }); entry.querySelector(".previewCheckbox").addEventListener("click", e => { if (e.currentTarget.checked) themeRepoModal.querySelectorAll(".previewCheckbox").forEach(checkbox => { if (e.currentTarget != checkbox) { checkbox.checked = false; BDFDB.removeClass(checkbox.parentElement, BDFDB.disCN.switchvaluechecked); BDFDB.addClass(checkbox.parentElement, BDFDB.disCN.switchvalueunchecked); } }); frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"NewTheme",checked:e.currentTarget.checked,css:data.css},"*"); }); container.appendChild(entry); function setEntryState (state) { data.state = state; BDFDB.toggleClass(entry, "downloadable", state > 1); BDFDB.toggleClass(entry, "outdated", state == 1); BDFDB.toggleClass(entry, "updated", state < 1); let downloadbutton = entry.querySelector(".btn-download"); downloadbutton.innerText = state < 1 ? "Updated" : (state > 1 ? "Download" : "Outdated"); downloadbutton.style.setProperty("background-color", "rgb(" + (state < 1 ? "67,181,129" : (state > 1 ? "114,137,218" : "241,71,71")) + ")", state > 1 ? "" : "important"); themeRepoModal.entries[data.url] = data; }; } sortEntries (themeRepoModal) { if (!themeRepoModal || typeof themeRepoModal.entries != "object") return; let container = themeRepoModal.querySelector(".themes"); if (!container) return; let searchstring = themeRepoModal.querySelector(BDFDB.dotCN.searchbarinput).value.replace(/[<|>]/g, "").toUpperCase(); let entries = themeRepoModal.entries; if (themeRepoModal.querySelector("#input-hideupdated").checked) entries = BDFDB.filterObject(entries, entry => {return entry.state < 1 ? null : entry;}); if (themeRepoModal.querySelector("#input-hideoutdated").checked) entries = BDFDB.filterObject(entries, entry => {return entry.state == 1 ? null : entry;}); if (themeRepoModal.querySelector("#input-hidedownloadable").checked) entries = BDFDB.filterObject(entries, entry => {return entry.state > 1 ? null : entry;}); entries = BDFDB.filterObject(entries, entry => {return entry.search.indexOf(searchstring) > -1 ? entry : null;}); let sortfilter = themeRepoModal.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue).getAttribute("option"); entries = BDFDB.sortObject(entries, sortfilter == "new" && !themeRepoModal.querySelector(".newentries-tag") ? "name" : sortfilter); if (themeRepoModal.querySelector(".order-filter " + BDFDB.dotCN.quickselectvalue).getAttribute("option") == "desc") entries = BDFDB.reverseObject(entries); let entrypositions = Object.keys(entries); themeRepoModal.querySelector(".themeAmount").innerText = "ThemeRepo Repository " + entrypositions.length + "/" + Object.keys(this.loadedThemes).length + " Themes"; for (let li of container.children) { let pos = entrypositions.indexOf(li.getAttribute("data-url")); if (pos > -1) { li.querySelectorAll(BDFDB.dotCNC._reponame + BDFDB.dotCNC._repoversion + BDFDB.dotCNC._repoauthor + BDFDB.dotCN._repodescription).forEach(ele => { if (searchstring && searchstring.length > 2 || ele.querySelector(BDFDB.dotCN.highlight)) ele.innerHTML = BDFDB.highlightText(ele.innerText, searchstring); }); li.style.setProperty("order", pos, "important"); } else li.style.removeProperty("order"); BDFDB.toggleEles(li, pos > -1); } } loadThemes () { BDFDB.removeEles(".themerepo-loadingicon"); var settings = BDFDB.loadAllData(this, "settings"); var getThemeInfo, outdated = 0, newentries = 0, i = 0; var tags = ["name","description","author","version"]; var newentriesdata = BDFDB.loadAllData(this, "newentriesdata"); var newentriesdata = BDFDB.loadAllData(this, "newentriesdata"), ownlist = BDFDB.loadData("ownlist", this, "ownlist") || []; this.cachedThemes = (newentriesdata.urlbase64 ? atob(newentriesdata.urlbase64).split("\n") : []).concat(ownlist); let request = require("request"); request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/ThemeRepo/res/ThemeList.txt", (error, response, result) => { if (!error && result) { result = result.replace(/[\r\t]/g, ""); BDFDB.saveData("urlbase64", btoa(result), this, "newentriesdata"); this.loadedThemes = {}; this.grabbedThemes = result.split("\n"); this.foundThemes = this.grabbedThemes.concat(ownlist); this.loading = {is:true, timeout:setTimeout(() => { clearTimeout(this.loading.timeout); if (this.started) { if (this.loading.is && this.loading.amount < 4) setTimeout(() => {this.loadThemes();},10000); this.loading = {is: false, timeout:null, amount:this.loading.amount}; } },1200000), amount:this.loading.amount+1}; var loadingiconwrapper = document.querySelector(BDFDB.dotCN.app + "> .repo-loadingwrapper"); if (!loadingiconwrapper) { loadingiconwrapper = BDFDB.htmlToElement(`
      `); document.querySelector(BDFDB.dotCN.app).appendChild(loadingiconwrapper); } var loadingicon = BDFDB.htmlToElement(this.themeRepoLoadingIconMarkup); loadingicon.addEventListener("mouseenter", () => {BDFDB.createTooltip("Loading ThemeRepo",loadingicon,{type:"left",delay:500});}) loadingiconwrapper.appendChild(loadingicon); getThemeInfo(() => { if (!this.started) { clearTimeout(this.loading.timeout); return; } BDFDB.removeEles(loadingicon, ".themerepo-loadingicon"); if (!loadingiconwrapper.firstChild) BDFDB.removeEles(loadingiconwrapper); clearTimeout(this.loading.timeout); this.loading = {is:false, timeout:null, amount:this.loading.amount}; console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Finished fetching Themes."); if (document.querySelector(".bd-themerepobutton")) BDFDB.showToast(`Finished fetching Themes.`, {type:"success"}); if ((settings.notifyOutdated || settings.notifyOutdated == undefined) && outdated > 0) { var oldbarbutton = document.querySelector(".themerepo-outdate-notice " + BDFDB.dotCN.noticedismiss); if (oldbarbutton) oldbarbutton.click(); var bar = BDFDB.createNotificationsBar(`${outdated} of your Themes ${outdated == 1 ? "is" : "are"} outdated. Check:`,{type:"danger",btn:"ThemeRepo",selector:"themerepo-notice themerepo-outdate-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { this.openThemeRepoModal({showOnlyOutdated:true}); bar.querySelector(BDFDB.dotCN.noticedismiss).click(); }); } if ((settings.notifyNewentries || settings.notifyNewentries == undefined) && newentries > 0) { var oldbarbutton = document.querySelector(".themerepo-newentries-notice " + BDFDB.dotCN.noticedismiss); if (oldbarbutton) oldbarbutton.click(); var bar = BDFDB.createNotificationsBar(`There ${newentries == 1 ? "is" : "are"} ${newentries} new Theme${newentries == 1 ? "" : "s"} in the Repo. Check:`,{type:"success",btn:"ThemeRepo",selector:"themerepo-notice themerepo-newentries-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { this.openThemeRepoModal({forcedSort:"new",forcedOrder:"asc"}); bar.querySelector(BDFDB.dotCN.noticedismiss).click(); }); } if (BDFDB.myData.id == "278543574059057154") { let wrongUrls = []; for (let url of this.foundThemes) if (url && !this.loadedThemes[url] && !wrongUrls.includes(url)) wrongUrls.push(url); if (wrongUrls.length > 0) { var bar = BDFDB.createNotificationsBar(`ThemeRepo: ${wrongUrls.length} Theme${wrongUrls.length > 1 ? "s" : ""} could not be loaded.`, {type:"danger",btn:"List",selector:"themerepo-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { var toast = BDFDB.showToast(wrongUrls.join("\n"),{type:"error"}); toast.style.overflow = "hidden"; console.log(wrongUrls.length == 1 ? wrongUrls[0] : wrongUrls); }); } } }); } }); getThemeInfo = (callback) => { if (i >= this.foundThemes.length || !this.started || !this.loading.is) { callback(); return; } let url = this.foundThemes[i]; request(url, (error, response, body) => { if (!response) { if (url && BDFDB.getAllIndexes(this.foundThemes, url).length < 2) this.foundThemes.push(url); } else if (body && body.indexOf("404: Not Found") != 0 && response.statusCode == 200) { let theme = {}; let text = body; if (text.split("*//").length > 1 && text.split("\n").length > 1) { for (let tag of tags) { let result = text.replace(new RegExp("\\s*\:\\s*", "g"), ":").replace(new RegExp("\\s*\}\\s*", "g"), "}").split('"' + tag + '":"'); result = result.length > 1 ? result[1].split('",')[0].split('"}')[0] : null; result = result && tag != "version" ? result.charAt(0).toUpperCase() + result.slice(1) : result; theme[tag] = result; } let valid = true; for (let tag of tags) { if (theme[tag] === null) valid = false; } if (valid) { theme.css = text.split("\n").slice(1).join("\n").replace(new RegExp("[\\r|\\n|\\t]", "g"), ""); theme.url = url; this.loadedThemes[url] = theme; var instTheme = window.bdthemes[theme.name]; if (instTheme && instTheme.author.toUpperCase() == theme.author.toUpperCase() && instTheme.version != theme.version) outdated++; if (!this.cachedThemes.includes(url)) newentries++; } } } i++; getThemeInfo(callback); }); } } checkForNewThemes () { let request = require("request"); request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/ThemeRepo/res/ThemeList.txt", (error, response, result) => { if (response && !BDFDB.equals(result.split("\n"), this.grabbedThemes)) { this.loading = {is:false, timeout:null, amount:0}; this.loadThemes(); } }); } downloadTheme (data) { let request = require("request"); request(data.url, (error, response, body) => { if (error) { BDFDB.showToast(`Unable to download Theme "${data.name}".`, {type:"danger"}); } else { let filename = data.url.split("/"); this.createThemeFile(filename[filename.length - 1], body); } }); } createThemeFile (filename, content) { let fileSystem = require("fs"); let path = require("path"); var file = path.join(BDFDB.getThemesFolder(), filename); fileSystem.writeFile(file, content, (error) => { if (error) { BDFDB.showToast(`Unable to save Theme "${filename}".`, {type:"danger"}); } else { BDFDB.showToast(`Successfully saved Theme "${filename}".`, {type:"success"}); } }); } applyTheme (data) { var name = data.name; if (BDFDB.isThemeEnabled(name) == false) { BDFDB.removeEles(`style#${name}`); document.head.appendChild(BDFDB.htmlToElement(``)); themeCookie[name] = true; themeModule.saveThemeData(); console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Applied Theme " + name + "."); } } deleteThemeFile (data) { let fileSystem = require("fs"); let path = require("path"); let filename = data.url.split("/"); filename = filename[filename.length - 1]; var file = path.join(BDFDB.getThemesFolder(), filename); fileSystem.unlink(file, (error) => { if (error) BDFDB.showToast(`Unable to delete Theme "${filename}".`, {type:"danger"}); else BDFDB.showToast(`Successfully deleted Theme "${filename}".`, {type:"success"}); }); } removeTheme (data) { var name = data.name; if (BDFDB.isThemeEnabled(name) == true) { BDFDB.removeEles(`style#${name}`); themeCookie[name] = false; delete bdthemes[name]; themeModule.saveThemeData(); console.log(`%c[${this.name}]%c`, "color: #3a71c1; font-weight: 700;", "", "Removed Theme " + name + "."); } } }