//META{"name":"RepoControls","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/RepoControls","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/RepoControls/RepoControls.plugin.js"}*//
class RepoControls {
getName () {return "RepoControls";}
getVersion () {return "1.2.8";}
getAuthor () {return "DevilBro";}
getDescription () {return "Lets you sort and filter your list of downloaded Themes and Plugins.";}
initConstructor () {
this.changelog = {
"fixed":[["Canary/PTB","Fixed the plugin for canary and ptb"]]
};
this.patchModules = {
"V2C_List":"componentDidMount",
"V2C_PluginCard": ["componentDidMount","componentDidUpdate"],
"V2C_ThemeCard": ["componentDidMount","componentDidUpdate"]
};
this.sortings = {
sort: {
name: "Name",
author: "Author",
version: "Version",
description: "Description",
enabled: "Enabled",
adddate: "Added",
moddate: "Modified"
},
order: {
asc: "Ascending",
desc: "Descending"
}
};
this.repoControlsMarkup =
`
Sort by:
${this.sortings.sort[Object.keys(this.sortings.sort)[0]]}
Order:
${this.sortings.order[Object.keys(this.sortings.order)[0]]}
`;
this.sortPopoutMarkup =
``;
this.orderPopoutMarkup =
``;
this.editButtonMarkup =
``;
this.deleteButtonMarkup =
``;
this.css = `
#bd-settingspane-container .editIcon,
#bd-settingspane-container .trashIcon {
margin: 0 5px 0 -2px;
cursor: pointer;
vertical-align: top;
color: #72767d;
}
${BDFDB.dotCN.themedark} #bd-settingspane-container .editIcon,
${BDFDB.dotCN.themedark} #bd-settingspane-container .trashIcon {
color: #dcddde;
}`;
this.defaults = {
settings: {
addEditButton: {value:true, description:"Adds an Edit Button to your Plugin and Theme List."},
addDeleteButton: {value:true, description:"Adds a Delete Button to your Plugin and Theme List."},
confirmDelete: {value:true, description:"Asks for your confirmation before deleting a File."}
},
sortings: {
sort: {value:"name"},
order: {value:"asc"}
}
};
}
getSettingsPanel () {
if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return;
let settings = BDFDB.getAllData(this, "settings");
let settingshtml = `${this.name}
`;
for (let key in settings) {
settingshtml += `
`;
}
settingshtml += `
`;
let settingspanel = BDFDB.htmlToElement(settingshtml);
BDFDB.initElements(settingspanel, this);
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.fs = require("fs");
this.path = require("path");
this.dirs = {theme: BDFDB.getThemesFolder(), plugin: BDFDB.getPluginsFolder()};
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) {
BDFDB.removeEles(".repo-controls","#bd-settingspane-container .trashIcon");
BDFDB.removeClasses("repocontrols-added");
for (let list of document.querySelectorAll(BDFDB.dotCNS._repolist)) {
list.style.removeProperty("display");
list.style.removeProperty("flex-direction");
for (let li of list.querySelectorAll("li")) {
li.style.removeProperty("display");
li.style.removeProperty("order");
var checkbox = li.querySelector(BDFDB.dotCN._repocheckbox);
if (checkbox) checkbox.removeEventListener("change", checkbox.changeRepoControlsListener);
}
}
BDFDB.unloadMessage(this);
}
}
// begin of own functions
processV2CList (instance, container) {
if (instance._reactInternalFiber.key) this.addControls(instance._reactInternalFiber.key.split("-")[0], container);
}
processV2CPluginCard (instance, wrapper, methodnames) {
if (wrapper.querySelector(BDFDB.dotCN._reponame)) {
let settings = BDFDB.getAllData(this, "settings");
if (instance.props && settings.addDeleteButton) this.addDeleteButton("plugin", wrapper);
if (instance.props && settings.addEditButton) this.addEditButton("plugin", wrapper);
if (methodnames.includes("componentDidUpdate")) this.changeTextToHTML(wrapper, "");
}
}
processV2CThemeCard (instance, wrapper, methodnames) {
if (wrapper.querySelector(BDFDB.dotCN._reponame)) {
let settings = BDFDB.getAllData(this, "settings");
if (instance.props && settings.addDeleteButton) this.addDeleteButton("theme", wrapper);
if (instance.props && settings.addEditButton) this.addEditButton("theme", wrapper);
if (methodnames.includes("componentDidUpdate")) this.changeTextToHTML(wrapper, "");
}
}
addEditButton (type, wrapper) {
if (!type || !wrapper || wrapper.querySelector(".editIcon")) return;
let name = wrapper.getAttribute("data-name");
let controls = wrapper.querySelector(BDFDB.dotCN._repocontrols);
if (!name || !controls) return;
let path = global[`bd${type}s`] && global[`bd${type}s`][name] ? this.path.join(this.dirs[type], global[`bd${type}s`][name].filename) : null;
if (!path) return;
let button = BDFDB.htmlToElement(this.editButtonMarkup);
button.addEventListener("click", () => {
if (!require("electron").shell.openItem(path)) BDFDB.showToast(`Unable to open ${type} "${name}".`, {type:"danger"});;
});
button.addEventListener("mouseenter", e => {
BDFDB.createTooltip(`Edit ${type[0].toUpperCase() + type.slice(1)}`, e.currentTarget, {type:"top",selector:"repocontrols-editicon-tooltip"});
});
controls.insertBefore(button, controls.firstElementChild);
}
addDeleteButton (type, wrapper) {
if (!type || !wrapper || wrapper.querySelector(".trashIcon")) return;
let name = wrapper.getAttribute("data-name");
let controls = wrapper.querySelector(BDFDB.dotCN._repocontrols);
if (!name || !controls) return;
let path = global[`bd${type}s`] && global[`bd${type}s`][name] ? this.path.join(this.dirs[type], global[`bd${type}s`][name].filename) : null;
if (!path) return;
let button = BDFDB.htmlToElement(this.deleteButtonMarkup);
button.addEventListener("click", () => {
let deleteFile = () => {
this.fs.unlink(path, (error) => {
if (error) BDFDB.showToast(`Unable to delete ${type} "${name}".`, {type:"danger"});
else BDFDB.showToast(`Successfully deleted ${type} "${name}".`, {type:"success"});
});
};
if (!BDFDB.getData("confirmDelete", this, "settings")) deleteFile();
else BDFDB.openConfirmModal(this, `Are you sure you want to delete the ${type} "${name}"?`, () => {
deleteFile();
});
});
button.addEventListener("mouseenter", e => {
BDFDB.createTooltip(`Delete ${type[0].toUpperCase() + type.slice(1)}`, e.currentTarget, {type:"top",selector:"repocontrols-trashicon-tooltip"});
});
controls.insertBefore(button, controls.firstElementChild);
}
addControls (type, container) {
if (!type || !container) return;
BDFDB.removeEles(".repo-controls");
container.style.setProperty("display", "flex", "important");
container.style.setProperty("flex-direction", "column", "important");
let sortings = BDFDB.getAllData(this, "sortings");
let repocontrols = BDFDB.htmlToElement(this.repoControlsMarkup);
repocontrols.insertBefore(BDFDB.createSearchBar("small"), repocontrols.firstElementChild);
BDFDB.initElements(repocontrols, this);
container.parentElement.insertBefore(repocontrols, container);
let sortfilter = repocontrols.querySelector(".sort-filter " + BDFDB.dotCN.quickselectvalue);
sortfilter.setAttribute("option", sortings.sort);
sortfilter.innerText = this.sortings.sort[sortings.sort];
let orderfilter = repocontrols.querySelector(".order-filter " + BDFDB.dotCN.quickselectvalue);
orderfilter.setAttribute("option", sortings.order);
orderfilter.innerText = this.sortings.order[sortings.order];
BDFDB.addChildEventListener(repocontrols, "keyup", BDFDB.dotCN.searchbarinput, () => {
clearTimeout(repocontrols.searchTimeout);
repocontrols.searchTimeout = setTimeout(() => {this.sortEntries(container, repocontrols);},1000);
});
BDFDB.addChildEventListener(repocontrols, "click", BDFDB.dotCN.searchbarclear + BDFDB.dotCN.searchbarvisible, () => {
this.sortEntries(container, repocontrols);
});
BDFDB.addChildEventListener(repocontrols, "click", ".btn-enableall", e => {
this.toggleAll(type, container, true);
});
BDFDB.addChildEventListener(repocontrols, "click", ".btn-disableall", e => {
this.toggleAll(type, container, false);
});
BDFDB.addChildEventListener(repocontrols, "click", ".sort-filter", e => {
BDFDB.createSortPopout(e.currentTarget, this.sortPopoutMarkup, () => {
BDFDB.saveData("sort", sortfilter.getAttribute("option"), this, "sortings");
this.sortEntries(container, repocontrols);
});
});
BDFDB.addChildEventListener(repocontrols, "click", ".order-filter", e => {
BDFDB.createSortPopout(e.currentTarget, this.orderPopoutMarkup, () => {
BDFDB.saveData("order", orderfilter.getAttribute("option"), this, "sortings");
this.sortEntries(container, repocontrols);
});
});
BDFDB.addClass(container, "repocontrols-added");
container.entries = {};
for (let li of container.children) {
if (li.querySelector(BDFDB.dotCN._reponame)) {
let name = li.querySelector(BDFDB.dotCN._reponame).textContent;
let version = li.querySelector(BDFDB.dotCN._repoversion).textContent;
let author = li.querySelector(BDFDB.dotCN._repoauthor).textContent;
let description = li.querySelector(BDFDB.dotCN._repodescription).textContent;
let enabled = li.querySelector(BDFDB.dotCN._repocheckbox).checked;
let path = global[`bd${type}s`] && global[`bd${type}s`][name] ? this.path.join(this.dirs[type], global[`bd${type}s`][name].filename) : null;
let stats = path ? this.fs.statSync(path) : null;
container.entries[name] = {
search: (name + " " + version + " " + author + " " + description).toUpperCase(),
origName: name,
name: (name).toUpperCase(),
version: (version).toUpperCase(),
author: (author).toUpperCase(),
description: (description).toUpperCase(),
type: type,
path: path,
adddate: stats ? stats.atime.getTime() : null,
moddate: stats ? stats.mtime.getTime() : null,
enabled: enabled ? 0 : 1
};
}
}
this.sortEntries(container, repocontrols);
}
sortEntries (container, repocontrols) {
if (typeof container.entries != "object") return;
let searchstring = repocontrols.querySelector(BDFDB.dotCN.searchbarinput).value.replace(/[<|>]/g, "").toUpperCase();
let sortings = BDFDB.getAllData(this, "sortings");
let entries = BDFDB.filterObject(container.entries, entry => {return entry.search.indexOf(searchstring) > -1 ? entry : null;});
entries = BDFDB.sortObject(entries, sortings.sort);
if (sortings.order == "desc") entries = BDFDB.reverseObject(entries);
let entrypositions = Object.keys(entries);
for (let li of container.children) {
let name = li.getAttribute("data-name");
let pos = entrypositions.indexOf(name);
if (pos > -1) {
this.changeTextToHTML(li, searchstring);
li.style.setProperty("order", pos, "important");
var checkbox = li.querySelector(BDFDB.dotCN._repocheckbox);
if (checkbox) {
checkbox.removeEventListener("change", checkbox.changeRepoControlsListener);
checkbox.changeRepoControlsListener = () => {entries[name].enabled = checkbox.checked ? 0 : 1};
checkbox.addEventListener("change", checkbox.changeRepoControlsListener);
}
}
else li.style.removeProperty("order");
BDFDB.toggleEles(li, pos > -1)
}
}
changeTextToHTML (wrapper, searchstring) {
if (!wrapper || !wrapper.tagName) return;
for (let ele of wrapper.querySelectorAll(BDFDB.dotCNC._reponame + BDFDB.dotCNC._repoversion + BDFDB.dotCNC._repoauthor + BDFDB.dotCN._repodescription)) {
var string = ele.firstElementChild ? ele.innerHTML : ele.innerText;
if (BDFDB.containsClass(ele, BDFDB.disCN._repodescription)) {
ele.style.display = "block";
if (searchstring && searchstring.length > 2) ele.innerHTML = BDFDB.highlightText(string, searchstring);
else ele.innerHTML = string;
}
else if (searchstring && searchstring.length > 2 || ele.querySelector(BDFDB.dotCN.highlight)) ele.innerHTML = BDFDB.highlightText(string, searchstring);
}
}
toggleAll (type, container, enable) {
BDFDB.openConfirmModal(this, `Are you sure you want to ${enable ? "enable" : "disable"} all ${type[0].toUpperCase() + type.slice(1)}s?`, () => {
for (let header of container.querySelectorAll(BDFDB.dotCN._repoheader)) {
if (header.querySelector(BDFDB.dotCN._reponame).textContent.toLowerCase().indexOf(this.name.toLowerCase()) != 0) {
let switchwrap = header.querySelector(BDFDB.dotCN._repocheckboxwrap);
if (switchwrap) {
let switchinner = switchwrap.querySelector(BDFDB.dotCN._repocheckboxinner);
let switchinput = switchwrap.querySelector(BDFDB.dotCN._repocheckbox);
if (switchinner && switchinput) {
if (BDFDB.containsClass(switchinner, BDFDB.disCN._repocheckboxchecked) && !enable) switchinput.click();
else if (!BDFDB.containsClass(switchinner, BDFDB.disCN._repocheckboxchecked) && enable) switchinput.click();
}
}
}
}
});
}
}