//META{"name":"ThemeRepo"}*// class ThemeRepo { initConstructor () { this.sortings = { sort: { name: "Name", author: "Author", version: "Version", description: "Description", state: "Update State", fav: "Favorites" }, order: { asc: "Ascending", desc: "Descending" } }; this.loading = false; this.grabbedThemes = []; this.foundThemes = []; this.loadedThemes = {}; this.updateInterval; this.themeFixerCSS = `#friends, .noChannel-Z1DQK7, .activityFeed-HeiGwL, .lfg-3xoFkI, .app, .layers-3iHuyZ, .layer-3QrUeG, .container-2lgZY8, .content-region, .guilds-wrapper, .search-l1Wz-Q .search-bar, .chat .inner-zqa7da, .search-results-wrap, .search-results-wrap .search-header, .search-results-wrap .search-result-message.hit, .sidebar-region, .ui-standard-sidebar-view, .channels-Ie2l6A, .container-2Thooq {background: rgba(0,0,0,0.3) !important;} .search-results-wrap .search-result-message.hit {box-shadow:none !important;} .titleBar-AC4pGV::after {content:""; position:absolute; z-index:-1; top:0; left:0; right:0; width:100%; height:22px; background: rgba(0,0,0,0.8) !important;} #friends .friends-table, .members-1998pB, .loading-316uYQ, .chat .content, .chat form, .chat, .content .flex-spacer, .messages-wrapper, .typing-2GQL18, .container-PNkimc, .headerBar-UHpsPw, .titleBar-AC4pGV, .titleWrapper-1l0xT9 .title-3qD0b-, .search-results-wrap .search-result::before, .search-results-wrap .search-result::after, .search-results-wrap .channel-name {background: transparent !important;} ::-webkit-scrollbar-thumb {border-color: transparent !important; background: rgba(0,0,0,0.8) !important;} ::-webkit-scrollbar, ::-webkit-scrollbar-track-piece {border-color: transparent !important; background: transparent !important;} ::-webkit-scrollbar-corner {display: none !important;}`; this.themeRepoButtonMarkup = ``; this.settingsContextEntryMarkup = `
Theme Repo
`; 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 = ` .discordPreview { width: 100vw !important; height: 100vh !important; position: absolute !important; z-index: 3400 !important; } .discordPreview ~ ${BDFDB.dotCN.appmount} { position: absolute !important; top: 0 !important; } .themerepo-sort-popout, .themerepo-order-popout, .themerepo-favicon-tooltip, .themerepo-giticon-tooltip { z-index: 3600 !important; } .themerepo-modal { position: relative !important; z-index: 3500 !important; } .themerepo-modal ${BDFDB.dotCN.modalinner} { min-height: 100%; } .themerepo-modal .themeEntry { overflow: visible !important; } .themerepo-modal .themeEntry .gitIcon, .themerepo-modal .themeEntry .favIcon, .themerepo-modal .themeEntry .trashIcon { margin-right: 5px; cursor: pointer; } .themerepo-modal .themeEntry .trashIcon, .themerepo-modal .themeEntry .favIcon { margin-left: auto; } .themerepo-modal .themeEntry .favIcon path { stroke: yellow; fill: none; } .themerepo-modal .themeEntry .favIcon.favorized path { stroke: yellow; fill: yellow; } .themerepo-modal .themeEntry.downloadable .trashIcon { display: none; } .themerepo-modal .themeEntry.downloadable .btn-download { background-color: rgb(114, 137, 218) !important; margin-left: auto !important; } .themerepo-modal .themeEntry.outdated .btn-download { background-color: rgb(240, 71, 71) !important; margin-left: 0 !important; } .themerepo-modal .themeEntry.updated .btn-download { background-color: rgb(67, 181, 129) !important; margin-left: 0 !important; } .themerepo-trashicon-tooltip{ z-index: 3500!important; } .themerepo-modal .themeEntry.jiiks .bda-right { flex: 1 1 auto; } .themerepo-modal .themeEntry.jiiks .bda-header, .themerepo-modal .themeEntry.jiiks .bda-footer { display: flex; align-items: center; margin: 0 !important; } .themerepo-modal .themeEntry.jiiks .bda-footer { margin-top: 33% !important; } .themerepo-modal .themeEntry.jiiks .previewCheckboxWrapper { margin-right: 5px; }`; } getName () {return "ThemeRepo";} 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.";} getVersion () {return "1.5.5";} getAuthor () {return "DevilBro";} 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 += `
      `; var settingspanel = $(settingshtml)[0]; BDFDB.initElements(settingspanel); $(settingspanel) .on("click", ".btn-addtheme", () => {this.addThemeToOwnList(settingspanel);}) .on("keyup", "#input-themeurl", (e) => {if (e.which == 13) this.addThemeToOwnList(settingspanel);}) .on("click", ".remove-theme", (e) => {this.removeThemeFromOwnList(e);}) .on("click", ".remove-all", () => {this.removeAllFromOwnList(settingspanel);}) .on("click", ".refresh-button", () => {this.loadThemes();}); return settingspanel; } //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"]); var observer = null; observer = new MutationObserver((changes, _) => { changes.forEach( (change, j) => { if (change.addedNodes) { change.addedNodes.forEach((node) => { this.checkIfThemesPage(node); }); } } ); }); BDFDB.addObserver(this, BDFDB.dotCN.layer + "[layer-id='user-settings']", {name:"innerSettingsWindowObserver",instance:observer}, {childList:true,subtree:true}); observer = new MutationObserver((changes, _) => { changes.forEach( (change, i) => { if (change.addedNodes) { change.addedNodes.forEach((node) => { setImmediate(() => { if (node && node.tagName && node.getAttribute("layer-id") == "user-settings") { BDFDB.addObserver(this, node, {name:"innerSettingsWindowObserver"}, {childList:true,subtree:true}); this.checkIfThemesPage(node); } }); }); } } ); }); BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true}); observer = new MutationObserver((changes, _) => { changes.forEach( (change, i) => { if (change.addedNodes) { change.addedNodes.forEach((node) => { if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) { this.onContextMenu(node); } }); } } ); }); BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"settingsContextObserver",instance:observer}, {childList: true}); var settingswindow = document.querySelector(BDFDB.dotCN.layer + "[layer-id='user-settings']"); if (settingswindow) this.checkIfThemesPage(settingswindow); this.loadThemes(); this.updateInterval = setInterval(() => {this.checkForNewThemes();},1000*60*30); } else { console.error(this.getName() + ": Fatal Error: Could not load BD functions!"); } } stop () { if (typeof BDFDB === "object") { clearInterval(this.updateInterval); $(".discordPreview, .themerepo-modal, .bd-themerepobutton").remove(); BDFDB.unloadMessage(this); } } // begin of own functions onContextMenu (context) { if (!context || !context.tagName || !context.parentElement) return; for (let entry of context.querySelectorAll(BDFDB.dotCN.contextmenuitem)) { if (entry.textContent == "BetterDiscord") { let innerObserver = new MutationObserver((changes, _) => { changes.forEach( (change, i) => { if (change.addedNodes) { change.addedNodes.forEach((node) => { if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu) && !node.querySelector(".themerepo-item")) { var innerEntries = node.querySelectorAll(BDFDB.dotCN.contextmenuitem); $(this.settingsContextEntryMarkup) .on("click", () => { if (!this.loading) $(context).hide(); this.openThemeRepoModal(); }) .insertAfter(innerEntries[innerEntries.length-1]); $(node).css("top", $(context).css("top").replace("px","") - $(node).outerHeight() + $(context).outerHeight()); } }); } } ); }); innerObserver.observe(entry, {childList: true}); break; } } } 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"); $(`
      ${url}
      `).appendTo(themeList); } } } 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) { if (confirm("Are you sure you want to remove all added Themes from your own list?")) { BDFDB.saveData("ownlist", [], this, "ownlist"); settingspanel.querySelectorAll(BDFDB.dotCN.hovercard).forEach(ele => {ele.remove();}); } } checkIfThemesPage (container) { if (container && container.tagName) { var folderbutton = container.querySelector(".bd-pfbtn"); if (folderbutton) { var buttonbar = folderbutton.parentElement; if (buttonbar && buttonbar.tagName) { var header = buttonbar.querySelector("h2"); if (header && header.innerText.toUpperCase() === "THEMES") { this.addThemeRepoButton(buttonbar); } } } } } addThemeRepoButton (container) { if (container && !container.querySelector(".bd-themerepobutton")) { $(container).find(".bda-description").css("display", "block"); $(this.themeRepoButtonMarkup) .insertAfter(container.querySelector(".bd-pfbtn")) .on("click", () => { this.openThemeRepoModal(); }) .on("mouseenter", (e) => { BDFDB.createTooltip("Open Theme Repo", e.currentTarget, {type:"top",selector:"themerepo-button-tooltip"}); }); } } openThemeRepoModal (showOnlyOutdated = false) { if (this.loading) { BDFDB.showToast(`Themes are still being fetched. Try again in some seconds.`, {type:"danger"}); return; } var frame = $(this.frameMarkup)[0]; var lightTheme = BDFDB.getDiscordTheme() == "theme-light"; var themeRepoModal = $(this.themeRepoModalMarkup); themeRepoModal.updateModal = true; themeRepoModal.enableSearch = false; var hiddenSettings = BDFDB.loadAllData(this, "hidden"); themeRepoModal.find("#input-darklight").prop("checked", lightTheme); themeRepoModal.find("#input-customcss").prop("checked", false); themeRepoModal.find("#input-themefixer").prop("checked", false); themeRepoModal.find("#input-hideupdated").prop("checked", hiddenSettings.updated || showOnlyOutdated); themeRepoModal.find("#input-hideoutdated").prop("checked", hiddenSettings.outdated && !showOnlyOutdated); themeRepoModal.find("#input-hidedownloadable").prop("checked", hiddenSettings.downloadable || showOnlyOutdated); if (!BDFDB.isRestartNoMoreEnabled()) themeRepoModal.find("#RNMoption").remove(); else themeRepoModal.find("#input-rnmstart").prop("checked", BDFDB.loadData("RNMstart", this, "settings")); themeRepoModal .on("keyup." + this.getName(), BDFDB.dotCN.searchbarinput, () => { clearTimeout(themeRepoModal.searchTimeout); themeRepoModal.searchTimeout = setTimeout(() => {this.addThemeEntries(themeRepoModal, frame);},1000); }) .on("click." + this.getName(), BDFDB.dotCN.searchbarclear + BDFDB.dotCN.searchbarvisible, () => { clearTimeout(themeRepoModal.searchTimeout); themeRepoModal.searchTimeout = setTimeout(() => {this.addThemeEntries(themeRepoModal, frame);},1000); }) .on("click." + this.getName(), BDFDB.dotCNC.modalclose + BDFDB.dotCN.backdrop, () => { frame.remove(); $(document).off("keyup." + this.getName()); $(window).off("message." + this.getName()); }) .on("click." + this.getName(), ".sort-filter", (e) => { this.openSortPopout(e, this.sortPopoutMarkup, themeRepoModal, frame); }) .on("click." + this.getName(), ".order-filter", (e) => { this.openSortPopout(e, this.orderPopoutMarkup, themeRepoModal, frame); }) .on("change." + this.getName(), "#input-darklight", (e) => { frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:$(e.target).prop("checked")},"*"); }) .on("change." + this.getName(), "#input-customcss", (e) => { var customCSS = document.querySelector("style#customcss"); if (customCSS && customCSS.innerText.length > 0) frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"CustomCSS",checked:$(e.target).prop("checked"),css:customCSS.innerText},"*"); }) .on("change." + this.getName(), "#input-themefixer", (e) => { frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"ThemeFixer",checked:$(e.target).prop("checked"),css:this.themeFixerCSS},"*"); }) .on("click." + this.getName(), "#download-themefixer", (e) => { this.createThemeFile("ThemeFixer.theme.css", `//META{"name":"ThemeFixer","description":"ThemeFixerCSS for transparent themes","author":"DevilBro","version":"1.0.1"}*//\n\n` + this.themeFixerCSS); }) .on("change." + this.getName(), ".hide-checkbox", (e) => { var hideButton = $(e.currentTarget); hiddenSettings[hideButton.val()] = hideButton.prop("checked"); BDFDB.saveAllData(hiddenSettings, this, "hidden"); }) .on("change." + this.getName(), "#input-rnmstart", (e) => { BDFDB.saveData("RNMstart", $(e.currentTarget).prop("checked"), this, "settings"); }) .on("click." + this.getName(), ".tab[tab=themes]:not(.selected)", (e) => { this.addThemeEntries(themeRepoModal, frame); }); $(document).off("keyup." + this.getName()) .on("keyup." + this.getName(), (e) => { keyPressed(e.which); }); $(window).off("message." + this.getName()) .on("message." + this.getName(), (e) => { e = e.originalEvent; 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.key); break; } } }); this.createThemeEntries(themeRepoModal, frame); BDFDB.appendModal(themeRepoModal); $(frame).insertBefore(BDFDB.dotCN.appmount); function keyPressed (key) { if (key == 17 && !themeRepoModal.find(BDFDB.dotCN.searchbarinput).is(":focus")) themeRepoModal.toggle(); if (key == 27) frame.remove(); } } openSortPopout (e, markup, modal, frame) { var wrapper = e.currentTarget; if (wrapper.classList.contains("popout-open")) return; wrapper.classList.add("popout-open"); var value = $(wrapper).find(BDFDB.dotCN.quickselectvalue); var popout = $(markup); $(BDFDB.dotCN.popouts).append(popout) .off("click", BDFDB.dotCN.contextmenuitem) .on("click", BDFDB.dotCN.contextmenuitem, (e2) => { value.text($(e2.currentTarget).text()); value.attr("option", $(e2.currentTarget).attr("option")); $(document).off("mousedown.sortpopout" + this.getName()); popout.remove(); this.addThemeEntries(modal, frame); setTimeout(() => {wrapper.classList.remove("popout-open");},300); }); popout .css("left", $(wrapper).offset().left + $(wrapper).outerWidth() + "px") .css("top", $(wrapper).offset().top + value.outerHeight() + "px") .find(BDFDB.dotCN.contextmenu).addClass(BDFDB.getDiscordTheme()); $(document).on("mousedown.sortpopout" + this.getName(), (e2) => { if (popout.has(e2.target).length == 0) { $(document).off("mousedown.sortpopout" + this.getName()); popout.remove(); setTimeout(() => {wrapper.classList.remove("popout-open");},300); } }); } createThemeEntries (modal, frame) { var favorites = BDFDB.loadAllData(this, "favorites"); modal.entries = []; for (let url in this.loadedThemes) { let theme = this.loadedThemes[url]; let div = $(this.themeEntryMarkup); var installedTheme = window.bdthemes[this.loadedThemes[url].name]; if (installedTheme && installedTheme.author.toUpperCase() == theme.author.toUpperCase()) { if (installedTheme.version != theme.version) { theme.state = 1; div.addClass("outdated") .find(".btn-download").text("Outdated"); } else { theme.state = 0; div.addClass("updated") .find(".btn-download").text("Updated"); } } else { theme.state = 2; div.addClass("downloadable") .find(".btn-download").text("Download"); } if (favorites[url]) { theme.fav = 0; div.find(".favIcon")[0].classList.add("favorized"); } else { theme.fav = 1; div.find(".favIcon")[0].classList.remove("favorized"); } modal.entries.push({ div: div, 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 }); } this.addThemeEntries(modal, frame); } addThemeEntries (modal, frame) { if (typeof modal.entries != "object") return; modal.find(".themeEntry").remove(); var searchstring = modal.find(BDFDB.dotCN.searchbarinput).val().replace(/[<|>]/g, "").toUpperCase(); var entries = modal.entries; if (modal.find("#input-hideupdated").prop("checked")) entries = entries.filter((entry) => {return entry.state != 0 ? entry : null;}); if (modal.find("#input-hideoutdated").prop("checked")) entries = entries.filter((entry) => {return entry.state != 1 ? entry : null;}); if (modal.find("#input-hidedownloadable").prop("checked")) entries = entries.filter((entry) => {return entry.state != 2 ? entry : null;}); entries = entries.filter((entry) => {return entry.search.indexOf(searchstring) > -1 ? entry : null;}); BDFDB.sortArrayByKey(entries, modal.find(".sort-filter " + BDFDB.dotCN.quickselectvalue).attr("option")); if (modal.find(".order-filter " + BDFDB.dotCN.quickselectvalue).attr("option") == "desc") entries.reverse(); modal.find(".themeAmount").text("Theme Repository " + entries.length + "/" + Object.keys(this.loadedThemes).length + " Themes"); var container = modal.find(".themes"); entries.forEach((entry) => { var div = entry.div; var values = [entry.name, entry.version, entry.author, entry.description]; if (searchstring.length > 0) { for (let i in values) values[i] = BDFDB.highlightText(values[i], searchstring); } div.find(".bda-name").html(values[0]); div.find(".bda-version").html(values[1]); div.find(".bda-author").html(values[2]); div.find(".bda-description").html(values[3]); div .on("change." + this.getName(), ".previewCheckbox", (e) => { modal.find(".previewCheckbox").not(e.target).prop("checked", false); modal.find(".previewCheckbox").each((_, checkBox) => { $(checkBox.parentElement) .toggleClass("valueChecked-3Bzkbm", $(checkBox).prop("checked")) .toggleClass("valueUnchecked-XR6AOk", $(checkBox).prop("checked")); }); frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"NewTheme",checked:$(e.target).prop("checked"),css:entry.css},"*"); }) .on("click." + this.getName(), ".favIcon", (e) => { e.currentTarget.classList.toggle("favorized"); if (e.currentTarget.classList.contains("favorized")) { entry.fav = 0; BDFDB.saveData(entry.url, true, this, "favorites"); } else { entry.fav = 1; BDFDB.removeData(entry.url, this, "favorites"); } }) .on("click." + this.getName(), ".gitIcon", (e) => { var giturl = null; if (entry.url.indexOf("https://raw.githubusercontent.com") == 0) { var temp = entry.url.replace("//raw.githubusercontent", "//github").split("/"); temp.splice(5, 0, "blob"); giturl = temp.join("/"); } else if (entry.url.indexOf("https://gist.githubusercontent.com/") == 0) { giturl = entry.url.replace("//gist.githubusercontent", "//gist.github").split("/raw/")[0]; } if (giturl) { window.open(giturl, "_blank"); } }) .on("click." + this.getName(), ".trashIcon", () => { if (div.hasClass("outdated") || div.hasClass("updated")) { entry.state = 2; div.removeClass("outdated").removeClass("updated").addClass("downloadable") .find(".btn-download").text("Download"); this.deleteThemeFile(entry); if (!BDFDB.isRestartNoMoreEnabled()) this.removeTheme(entry); } }) .on("mouseenter." + this.getName(), ".favIcon", (e) => { BDFDB.createTooltip("Favorize", e.currentTarget, {type:"top",selector:"themerepo-favicon-tooltip"}); }) .on("mouseenter." + this.getName(), ".gitIcon", (e) => { BDFDB.createTooltip("Go to Git", e.currentTarget, {type:"top",selector:"themerepo-giticon-tooltip"}); }) .on("mouseenter." + this.getName(), ".trashIcon", (e) => { BDFDB.createTooltip("Delete Themefile", e.currentTarget, {type:"top",selector:"themerepo-trashicon-tooltip"}); }) .on("click." + this.getName(), ".btn-download", () => { entry.state = 0; this.downloadTheme(entry); div.removeClass("downloadable").removeClass("outdated").addClass("updated") .find(".btn-download").text("Updated"); if (modal.find("#input-rnmstart").prop("checked")) setTimeout(() => {this.applyTheme(entry);},3000); }); container.append(div); }); } loadThemes () { 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 = true; getThemeInfo(() => { this.loading = false; console.log("ThemeRepo: Finished fetching Themes."); if (document.querySelector(".bd-themerepobutton")) BDFDB.showToast(`Finished fetching Themes.`, {type:"success"}); if (outdated > 0) { var text = `${outdated} of your Themes ${outdated == 1 ? "is" : "are"} outdated. Check:`; var bar = BDFDB.createNotificationsBar(text,{type:"danger",btn:"ThemeRepo",selector:"themerepo-notice"}); $(bar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (e) => { this.openThemeRepoModal(true); e.delegateTarget.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"}); $(bar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (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) { 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 { 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 installedTheme = window.bdthemes[theme.name]; if (installedTheme && installedTheme.author.toUpperCase() == theme.author.toUpperCase() && installedTheme.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.loadThemes(); }); } downloadTheme (entry) { let request = require("request"); request(entry.url, (error, response, body) => { if (error) { BDFDB.showToast(`Unable to download Theme "${entry.name}".`, {type:"danger"}); } else { let filename = entry.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 (entry) { var name = entry.name; if (BDFDB.isThemeEnabled(name) == false) { $(`style#${name}`).remove(); $("head").append(``); themeCookie[name] = true; themeModule.saveThemeData(); console.log("ThemeRepo: applied Theme " + name); } } deleteThemeFile (entry) { let fileSystem = require("fs"); let path = require("path"); let filename = entry.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 (entry) { var name = entry.name; if (BDFDB.isThemeEnabled(name) == true) { $(`style#${name}`).remove(); themeCookie[name] = false; delete bdthemes[name]; themeModule.saveThemeData(); console.log("ThemeRepo: removed Theme " + name); } } }