//META{"name":"ThemeRepo"}*// class ThemeRepo { getName () {return "ThemeRepo";} getVersion () {return "1.6.9";} 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.patchModules = { "V2C_List":"componentDidMount" }; this.sortings = { sort: { name: "Name", author: "Author", version: "Version", description: "Description", state: "Update State", fav: "Favorites" }, order: { asc: "Ascending", desc: "Descending" } }; this.loading = {is:false, timeout:null, amount:0}; 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.giftinventory + BDFDB.dotCNC.activityfeed + BDFDB.dotCNC.lfg + BDFDB.dotCNC.applicationstore + 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

      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.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;} } .discordPreview { width: 100vw !important; height: 100vh !important; position: absolute !important; z-index: 999 !important; } .discordPreview ~ ${BDFDB.dotCN.appmount} { position: absolute !important; top: 0 !important; } .discordPreview ~ ${BDFDB.dotCNS.appmount + BDFDB.dotCN.app} { opacity: 0 !important; visibility: hidden !important; } .${this.getName()}-modal.Repo-modal ${BDFDB.dotCN.modalinner} { min-height: 100%; min-width: 800px; width: 50%; } .${this.getName()}-modal .themeEntry ${BDFDB.dotCN._repocontrols} > * { margin-right: 5px !important; } .${this.getName()}-modal .themeEntry ${BDFDB.dotCN._repocontrols} > .previewCheckboxWrapper { margin-right: 0px !important; } .${this.getName()}-modal .themeEntry svg[fill="currentColor"], .${this.getName()}-modal .themeEntry ${BDFDB.dotCN.giffavoritebutton} { cursor: pointer; } .${this.getName()}-modal .themeEntry svg[fill="currentColor"], .${this.getName()}-modal .themeEntry ${BDFDB.dotCN.giffavoritebutton}:not(${BDFDB.dotCN.giffavoriteselected}) { color: #72767d !important; } ${BDFDB.dotCN.themedark} .${this.getName()}-modal .themeEntry svg[fill="currentColor"], ${BDFDB.dotCN.themedark} .${this.getName()}-modal .themeEntry ${BDFDB.dotCN.giffavoritebutton}:not(${BDFDB.dotCN.giffavoriteselected}) { color: #dcddde !important; } .${this.getName()}-modal .themeEntry.downloadable .trashIcon { opacity: 0 !important; pointer-events: none !important; }`; } getSettingsPanel () { if (!this.started || typeof BDFDB !== "object") return; var settingshtml = `
      ${this.getName()}
      `; 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.addChildEventListener(settingspanel, "click", ".btn-addtheme", () => {this.addThemeToOwnList(settingspanel);}); BDFDB.addChildEventListener(settingspanel, "click", "#input-themeurl", e => {if (e.which == 13) this.addThemeToOwnList(settingspanel);}); BDFDB.addChildEventListener(settingspanel, "click", ".remove-theme", e => {this.removeThemeFromOwnList(e);}); BDFDB.addChildEventListener(settingspanel, "click", ".remove-all", () => {this.removeAllFromOwnList();}) BDFDB.addChildEventListener(settingspanel, "click", ".refresh-button", () => { this.loading = {is:false, timeout:null, amount:0}; this.loadThemes(); }); } //legacy load () {} start () { var libraryScript = null; if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) { libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]'); if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"); document.head.appendChild(libraryScript); } this.startTimeout = setTimeout(() => {this.initialize();}, 30000); if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize(); else libraryScript.addEventListener("load", () => {this.initialize();}); } initialize () { if (typeof BDFDB === "object") { BDFDB.loadMessage(this); this.UserUtils = BDFDB.WebModules.findByProperties("getUsers"); this.IconUtils = BDFDB.WebModules.findByProperties("getUserAvatarURL"); this.loadThemes(); this.updateInterval = setInterval(() => {this.checkForNewThemes();},1000*60*30); BDFDB.WebModules.forceAllUpdates(this); } else { console.error(this.getName() + ": Fatal Error: Could not load BD functions!"); } } stop () { if (typeof BDFDB === "object") { clearInterval(this.updateInterval); clearTimeout(this.loading.timeout); BDFDB.removeEles(".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 && node.classList && node.className.includes("plugin-context-menu") && !node.querySelector(".themerepo-item")) { observer.disconnect(); 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) instance._reactInternalFiber.return.memoizedProps.closeContextMenu(); this.openThemeRepoModal(); }); item.parentElement.insertBefore(settingsContextEntry, item.nextElementSibling); node.style.setProperty("top", (menu.getBoundingClientRect().top - node.getBoundingClientRect().height + menu.getBoundingClientRect().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"); themeList.appendChild(BDFDB.htmlToElement(`
      ${url}
      `)); } } } 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 () { BDFDB.openConfirmModal(this, "Are you sure you want to remove all added Themes from your own list?", () => { BDFDB.saveData("ownlist", [], this, "ownlist"); BDFDB.removeEles("." + this.getName() + "-settings " + BDFDB.dotCN.hovercard); }); } openThemeRepoModal (showOnlyOutdated = false) { 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 user = this.UserUtils.getCurrentUser(); if (!user) return; var username = user.username; var id = user.id; var avatar = "url(" + (((user.avatar ? "" : "https://discordapp.com") + this.IconUtils.getUserAvatarURL(user)).split("?size")[0]) + ");"; var discriminator = user.discriminator; 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,avatar,discriminator,nativecss},"*"); frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:lightTheme},"*"); break; case "KeyUp": keyPressed(e.data); break; } } }; document.addEventListener("keyup", keyPressed); window.addEventListener("message", messageReceived); var frame = BDFDB.htmlToElement(this.frameMarkup); var lightTheme = BDFDB.getDiscordTheme() == BDFDB.disCN.themelight; var themeRepoModal = BDFDB.htmlToElement(this.themeRepoModalMarkup); var hiddenSettings = BDFDB.loadAllData(this, "hidden"); var darklightinput = themeRepoModal.querySelector("#input-darklight"); var customcssinput = themeRepoModal.querySelector("#input-customcss"); var themefixerinput = themeRepoModal.querySelector("#input-themefixer"); darklightinput.checked = lightTheme; customcssinput.checked = false; themefixerinput.checked = false; themeRepoModal.querySelector("#input-hideupdated").checked = hiddenSettings.updated || showOnlyOutdated; themeRepoModal.querySelector("#input-hideoutdated").checked = hiddenSettings.outdated && !showOnlyOutdated; themeRepoModal.querySelector("#input-hidedownloadable").checked = hiddenSettings.downloadable || showOnlyOutdated; if (!BDFDB.isRestartNoMoreEnabled()) themeRepoModal.querySelector("#RNMoption").remove(); else themeRepoModal.querySelector("#input-rnmstart").checked = BDFDB.loadData("RNMstart", this, "settings"); darklightinput.addEventListener("change", e => { frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:darklightinput.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, "settings"); }); 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 (!e.currentTarget.classList.contains(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; theme.fav = favorites[url] ? 0 : 1; 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: theme.fav, 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); } 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; let favbutton = entry.querySelector(BDFDB.dotCN.giffavoritebutton); favbutton.classList.toggle(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 (entry.classList.contains("outdated") || entry.classList.contains("updated")) { 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; checkbox.parentElement.classList.remove(BDFDB.disCN.switchvaluechecked); checkbox.parentElement.classList.add(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; entry.classList.toggle("downloadable", state > 1); entry.classList.toggle("outdated", state == 1); entry.classList.toggle("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")) + ")", "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;}); entries = BDFDB.sortObject(entries, themeRepoModal.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue).getAttribute("option")); 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 getThemeInfo, outdated = 0, i = 0; var tags = ["name","description","author","version"]; let request = require("request"); request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/ThemeRepo/res/ThemeList.txt", (error, response, result) => { if (response) { this.loadedThemes = {}; this.grabbedThemes = result.split("\n"); this.foundThemes = this.grabbedThemes.concat(BDFDB.loadData("ownlist", this, "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); if (!loadingiconwrapper.firstChild) BDFDB.removeEles(loadingiconwrapper); clearTimeout(this.loading.timeout); this.loading = {is:false, timeout:null, amount:this.loading.amount}; console.log(`%c[${this.getName()}]%c`, "color: #3a71c1; font-weight: 700;", "", "Finished fetching Themes."); if (document.querySelector(".bd-themerepobutton")) BDFDB.showToast(`Finished fetching Themes.`, {type:"success"}); if (outdated > 0) { var bar = BDFDB.createNotificationsBar(`${outdated} of your Themes ${outdated == 1 ? "is" : "are"} outdated. Check:`,{type:"danger",btn:"ThemeRepo",selector:"themerepo-notice"}); bar.querySelector(BDFDB.dotCN.noticebutton).addEventListener("click", e => { this.openThemeRepoModal(true); 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].replace(new RegExp("[\\r|\\n|\\t]", "g"), ""); this.foundThemes[i] = url; 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++; } } } 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.getName()}]%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.getName()}]%c`, "color: #3a71c1; font-weight: 700;", "", "Removed Theme " + name + "."); } } }