Add edit button

This commit is contained in:
Jean Ouina 2020-07-15 19:20:27 +02:00
parent 22ff405d40
commit c96f94b314
8 changed files with 399 additions and 388 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -77,11 +77,12 @@ export const settings = {
"Normalize Classes": {id: "fork-ps-4", info: "Adds stable classes to elements to help themes. (e.g. adds .da-channels to .channels-Ie2l6A)", implemented: true, hidden: false, cat: "core", category: "modules"},
/* Content */
"Content Error Modal": {id: "fork-ps-1", info: "Shows a modal with plugin/theme errors", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Scan Plugins": {id: "fork-ps-6", info: "Scan plugins for any threat that can be hidden inside.", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Show Toasts": {id: "fork-ps-2", info: "Shows a small notification for important information", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Scroll To Settings": {id: "fork-ps-3", info: "Auto-scrolls to a plugin's settings when the button is clicked (only if out of view)", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Automatic Loading": {id: "fork-ps-5", info: "Automatically loads, reloads, and unloads plugins and themes", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Content Error Modal": {id: "fork-ps-1", info: "Shows a modal with plugin/theme errors", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Scan Plugins": {id: "fork-ps-6", info: "Scan plugins for any threat that can be hidden inside.", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Show Toasts": {id: "fork-ps-2", info: "Shows a small notification for important information", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Scroll To Settings": {id: "fork-ps-3", info: "Auto-scrolls to a plugin's settings when the button is clicked (only if out of view)", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Automatic Loading": {id: "fork-ps-5", info: "Automatically loads, reloads, and unloads plugins and themes", implemented: true, hidden: false, cat: "core", category: "content manager"},
"Enable Edit Button": {id: "fork-ps-7", info: "Enable an Edit Button on the plugin and theme panel.", implemented: true, hidden: false, cat: "core", category: "content manager"},
/* Developer */
"Developer Mode": {id: "bda-gs-8", info: "Developer Mode Toggle", implemented: true, hidden: false, cat: "core", category: "developer settings"},
@ -135,6 +136,7 @@ export const defaultCookie = {
"fork-ps-4": true,
"fork-ps-5": true,
"fork-ps-6": true,
"fork-ps-7": false,
"fork-es-2": false,
"fork-es-3": true,
"fork-wp-1": false,

View File

@ -1,138 +1,138 @@
import WebpackModules from "./webpackModules";
const normalizedPrefix = "da";
const randClass = new RegExp(`^(?!${normalizedPrefix}-)((?:[A-Za-z]|[0-9]|-)+)-(?:[A-Za-z]|[0-9]|-|_){6}$`);
export default new class ClassNormalizer {
constructor(){
window.Lightcord.BetterDiscord.BDEvents = this
}
stop() {
if (!this.hasPatched) return;
this.unpatchClassModules(WebpackModules.findAll(this.moduleFilter.bind(this)));
this.revertElement(document.querySelector("#app-mount"));
this.hasPatched = false;
}
start() {
if (this.hasPatched) return;
this.patchClassModules(WebpackModules.findAll(this.moduleFilter.bind(this)));
this.normalizeElement(document.querySelector("#app-mount"));
this.hasPatched = true;
this.patchDOMMethods();
}
patchClassModules(modules) {
for (const module of modules) {
this.patchClassModule(normalizedPrefix, module);
}
}
unpatchClassModules(modules) {
for (const module of modules) {
this.unpatchClassModule(normalizedPrefix, module);
}
}
shouldIgnore(value) {
if (!isNaN(value)) return true;
if (value.endsWith("px") || value.endsWith("ch") || value.endsWith("em") || value.endsWith("ms")) return true;
if (value.startsWith("layerContainer-")) return true;
if (value.startsWith("#") && (value.length == 7 || value.length == 4)) return true;
if (value.includes("calc(") || value.includes("rgba")) return true;
return false;
}
moduleFilter(module) {
if (typeof module !== "object" || Array.isArray(module)) return false;
if (module.__esModule) return false;
if (!Object.keys(module).length) return false;
for (const baseClassName in module) {
const value = module[baseClassName];
if (typeof value !== "string") return false;
if (this.shouldIgnore(value)) continue;
if (value.split("-").length === 1) return false;
if (!randClass.test(value.split(" ")[0])) return false;
}
return true;
}
patchClassModule(componentName, classNames) {
for (const baseClassName in classNames) {
const value = classNames[baseClassName];
if (this.shouldIgnore(value)) continue;
const classList = value.split(" ");
for (const normalClass of classList) {
const match = normalClass.match(randClass);
if (!match || !match.length || match.length < 2) continue; // Shouldn't ever happen since they passed the moduleFilter, but you never know
const camelCase = match[1].split("-").map((s, i) => i ? s[0].toUpperCase() + s.slice(1) : s).join("");
classNames[baseClassName] += ` ${componentName}-${camelCase}`;
}
}
}
unpatchClassModule(componentName, classNames) {
for (const baseClassName in classNames) {
const value = classNames[baseClassName];
if (this.shouldIgnore(value)) continue;
let newString = "";
const classList = value.split(" ");
for (const normalClass of classList) {
if (normalClass.startsWith(`${componentName}-`)) continue;
newString += ` ${normalClass}`;
}
classNames[baseClassName] = newString.trim();
}
}
normalizeElement(element) {
if (!(element instanceof Element)) return;
const classes = element.classList;
for (let c = 0, clen = classes.length; c < clen; c++) {
if (!randClass.test(classes[c])) continue;
const match = classes[c].match(randClass)[1];
const newClass = match.split("-").map((s, i) => i ? s[0].toUpperCase() + s.slice(1) : s).join("");
element.classList.add(`${normalizedPrefix}-${newClass}`);
}
for (const child of element.children) this.normalizeElement(child);
}
revertElement(element) {
if (!(element instanceof Element)) return;
if (element.children && element.children.length) this.revertElement(element.children[0]);
if (element.nextElementSibling) this.revertElement(element.nextElementSibling);
const classes = element.classList;
const toRemove = [];
for (let c = 0; c < classes.length; c++) {
if (classes[c].startsWith(`${normalizedPrefix}-`)) toRemove.push(classes[c]);
}
element.classList.remove(...toRemove);
}
patchDOMMethods() {
const contains = DOMTokenList.prototype.contains;
DOMTokenList.prototype.contains = function(token) {
// const tokens = token.split(" ");
return Reflect.apply(contains, this, [token.split(" ")[0]]);
// return tokens.every(t => contains.call(this, t));
};
const add = DOMTokenList.prototype.add;
DOMTokenList.prototype.add = function(...tokens) {
for (let t = 0; t < tokens.length; t++) {
tokens[t] = tokens[t].split(" ")[0];
}
return Reflect.apply(add, this, tokens);
};
const remove = DOMTokenList.prototype.remove;
DOMTokenList.prototype.remove = function(...tokens) {
for (let t = 0; t < tokens.length; t++) {
tokens[t] = tokens[t].split(" ")[0];
}
return Reflect.apply(remove, this, tokens);
};
}
import WebpackModules from "./webpackModules";
const normalizedPrefix = "da";
const randClass = new RegExp(`^(?!${normalizedPrefix}-)((?:[A-Za-z]|[0-9]|-)+)-(?:[A-Za-z]|[0-9]|-|_){6}$`);
export default new class ClassNormalizer {
constructor(){
window.Lightcord.BetterDiscord.ClassNormalizer = this
}
stop() {
if (!this.hasPatched) return;
this.unpatchClassModules(WebpackModules.findAll(this.moduleFilter.bind(this)));
this.revertElement(document.querySelector("#app-mount"));
this.hasPatched = false;
}
start() {
if (this.hasPatched) return;
this.patchClassModules(WebpackModules.findAll(this.moduleFilter.bind(this)));
this.normalizeElement(document.querySelector("#app-mount"));
this.hasPatched = true;
this.patchDOMMethods();
}
patchClassModules(modules) {
for (const module of modules) {
this.patchClassModule(normalizedPrefix, module);
}
}
unpatchClassModules(modules) {
for (const module of modules) {
this.unpatchClassModule(normalizedPrefix, module);
}
}
shouldIgnore(value) {
if (!isNaN(value)) return true;
if (value.endsWith("px") || value.endsWith("ch") || value.endsWith("em") || value.endsWith("ms")) return true;
if (value.startsWith("layerContainer-")) return true;
if (value.startsWith("#") && (value.length == 7 || value.length == 4)) return true;
if (value.includes("calc(") || value.includes("rgba")) return true;
return false;
}
moduleFilter(module) {
if (typeof module !== "object" || Array.isArray(module)) return false;
if (module.__esModule) return false;
if (!Object.keys(module).length) return false;
for (const baseClassName in module) {
const value = module[baseClassName];
if (typeof value !== "string") return false;
if (this.shouldIgnore(value)) continue;
if (value.split("-").length === 1) return false;
if (!randClass.test(value.split(" ")[0])) return false;
}
return true;
}
patchClassModule(componentName, classNames) {
for (const baseClassName in classNames) {
const value = classNames[baseClassName];
if (this.shouldIgnore(value)) continue;
const classList = value.split(" ");
for (const normalClass of classList) {
const match = normalClass.match(randClass);
if (!match || !match.length || match.length < 2) continue; // Shouldn't ever happen since they passed the moduleFilter, but you never know
const camelCase = match[1].split("-").map((s, i) => i ? s[0].toUpperCase() + s.slice(1) : s).join("");
classNames[baseClassName] += ` ${componentName}-${camelCase}`;
}
}
}
unpatchClassModule(componentName, classNames) {
for (const baseClassName in classNames) {
const value = classNames[baseClassName];
if (this.shouldIgnore(value)) continue;
let newString = "";
const classList = value.split(" ");
for (const normalClass of classList) {
if (normalClass.startsWith(`${componentName}-`)) continue;
newString += ` ${normalClass}`;
}
classNames[baseClassName] = newString.trim();
}
}
normalizeElement(element) {
if (!(element instanceof Element)) return;
const classes = element.classList;
for (let c = 0, clen = classes.length; c < clen; c++) {
if (!randClass.test(classes[c])) continue;
const match = classes[c].match(randClass)[1];
const newClass = match.split("-").map((s, i) => i ? s[0].toUpperCase() + s.slice(1) : s).join("");
element.classList.add(`${normalizedPrefix}-${newClass}`);
}
for (const child of element.children) this.normalizeElement(child);
}
revertElement(element) {
if (!(element instanceof Element)) return;
if (element.children && element.children.length) this.revertElement(element.children[0]);
if (element.nextElementSibling) this.revertElement(element.nextElementSibling);
const classes = element.classList;
const toRemove = [];
for (let c = 0; c < classes.length; c++) {
if (classes[c].startsWith(`${normalizedPrefix}-`)) toRemove.push(classes[c]);
}
element.classList.remove(...toRemove);
}
patchDOMMethods() {
const contains = DOMTokenList.prototype.contains;
DOMTokenList.prototype.contains = function(token) {
// const tokens = token.split(" ");
return Reflect.apply(contains, this, [token.split(" ")[0]]);
// return tokens.every(t => contains.call(this, t));
};
const add = DOMTokenList.prototype.add;
DOMTokenList.prototype.add = function(...tokens) {
for (let t = 0; t < tokens.length; t++) {
tokens[t] = tokens[t].split(" ")[0];
}
return Reflect.apply(add, this, tokens);
};
const remove = DOMTokenList.prototype.remove;
DOMTokenList.prototype.remove = function(...tokens) {
for (let t = 0; t < tokens.length; t++) {
tokens[t] = tokens[t].split(" ")[0];
}
return Reflect.apply(remove, this, tokens);
};
}
};

View File

@ -1,220 +1,220 @@
import ErrorBoundary from "./errorBoundary";
import ContentColumn from "./contentColumn";
import Tools from "./tools";
import ReloadIcon from "./reloadIcon";
import AddonCard from "./addoncard";
import Scroller from "./scroller";
import Dropdown from "./components/dropdown";
import Search from "./components/search";
import {settingsCookie, pluginCookie, themeCookie} from "../0globals";
import ContentManager from "../modules/contentManager";
import BDV2 from "../modules/v2";
import pluginModule from "../modules/pluginModule";
import themeModule from "../modules/themeModule";
import WebpackModules from "../modules/webpackModules";
import BdApi from "../modules/bdApi";
import Utils from "../modules/utils";
import tooltipWrap from "./tooltipWrap";
const Tooltip = WebpackModules.findByDisplayName("Tooltip");
const React = BDV2.react;
export default class CardList extends BDV2.reactComponent {
constructor(props) {
super(props);
this.state = {sort: "name", ascending: true, query: ""};
this.isPlugins = this.props.type == "plugins";
this.cookie = this.isPlugins ? pluginCookie : themeCookie;
this.manager = this.isPlugins ? pluginModule : themeModule;
this.sort = this.sort.bind(this);
this.reverse = this.reverse.bind(this);
this.search = this.search.bind(this);
}
openFolder() {
require("electron").shell.openItem(this.isPlugins ? ContentManager.pluginsFolder : ContentManager.themesFolder);
}
edit(name) {
console.log(name);
this.manager.edit(name);
}
async delete(name) {
const shouldDelete = await this.confirmDelete(name);
if (!shouldDelete) return;
this.manager.delete(name);
}
confirmDelete(name) {
return new Promise(resolve => {
BdApi.showConfirmationModal("Are You Sure?", `Are you sure you want to delete ${name}?`, {
danger: true,
confirmText: "Delete",
onConfirm: () => {resolve(true);},
onCancel: () => {resolve(false);}
});
});
}
get sortOptions() {
return [
{label: "Name", value: "name"},
{label: "Author", value: "author"},
{label: "Version", value: "version"},
{label: "Recently Added", value: "added"},
{label: "Last Modified", value: "modified"},
{label: "File Size", value: "size"},
];
}
get directions() {
return [
{label: "Ascending", value: true},
{label: "Descending", value: false}
];
}
reverse(value) {
this.setState({ascending: value});
}
sort(value) {
this.setState({sort: value});
}
search(event) {
this.setState({query: event.target.value.toLocaleLowerCase()});
}
getProps(addon) {
return {
key: this.getName(addon),
enabled: this.cookie[this.getName(addon)],
toggle: this.manager.toggle.bind(this.manager),
//edit: this.edit.bind(this),
remove: this.delete.bind(this),
addon: addon,
hash: addon.hash
};
}
getString(value) {
if (!value) return "???";
return typeof value == "string" ? value : value.toString();
}
get list(){
return this.props.type === "plugins" ? Object.values(bdplugins) : Object.values(bdthemes);
}
getAddons() {
const sortedAddons = this.list.sort((a, b) => {
const cap = this.state.sort.charAt(0).toUpperCase() + this.state.sort.slice(1);
const first = a.plugin && a.plugin[`get${cap}`] ? this.getString(a.plugin[`get${cap}`]()) : a[this.state.sort];
const second = b.plugin && b.plugin[`get${cap}`] ? this.getString(b.plugin[`get${cap}`]()) : b[this.state.sort];
if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());
if (first > second) return 1;
if (second > first) return -1;
return 0;
});
if (!this.state.ascending) sortedAddons.reverse();
const rendered = [];
for (let a = 0; a < sortedAddons.length; a++) {
const addon = sortedAddons[a];
if (this.state.query) {
let matches = null;
const name = this.getName(addon);
const author = this.getAuthor(addon);
const description = this.getDescription(addon);
const version = this.getVersion(addon);
if (name) matches = name.toLocaleLowerCase().includes(this.state.query);
if (author) matches = matches || author.toLocaleLowerCase().includes(this.state.query);
if (description) matches = matches || description.toLocaleLowerCase().includes(this.state.query);
if (version) matches = matches || version.toLocaleLowerCase().includes(this.state.query);
if (!matches) continue;
}
const props = this.getProps(addon);
rendered.push(<ErrorBoundary><AddonCard {...props} reload={!settingsCookie["fork-ps-5"] && this.manager.reload.bind(this.manager)} /></ErrorBoundary>);
}
return rendered;
}
getName(addon) {return this.getString(addon.plugin ? addon.plugin.getName() : addon.name);}
getAuthor(addon) {return this.getString(addon.plugin ? addon.plugin.getAuthor() : addon.author);}
getDescription(addon) {return this.getString(addon.plugin ? addon.plugin.getDescription() : addon.description);}
getVersion(addon) {return this.getString(addon.plugin ? addon.plugin.getVersion() : addon.version);}
renderCheckUpdates(){
if(!window.ZeresPluginLibrary)return null
if(!window.PluginUpdates)return null
if(typeof window.PluginUpdates.checkAll !== "function")return null
if(!this.isPlugins)return null
return <tooltipWrap text="Checks for updates of plugins that support this feature. Right-click for a list.">
<span style={{marginLeft: "10px"}}>
<Lightcord.Api.Components.inputs.Button color="brand" look="filled" size="min" hoverColor="default" onClick={() => {
try{
Utils.showToast("Plugin update check in progress.", {type: "info"})
window.PluginUpdates.checkAll()
.then(() => {
Utils.showToast("Plugin update check complete.", {type: "success"})
}).catch(err => {
console.error(err)
Utils.showToast("An error occured while checking update.", {type: "error"})
})
}catch(e){
console.error(e)
Utils.showToast("An error occured while checking update.", {type: "error"})
}
}} wrapper={false} disabled={false}>
Check for Updates
</Lightcord.Api.Components.inputs.Button>
</span>
</tooltipWrap>
}
render() {
const refreshIcon = <Tooltip color="black" position="top" text="Reload List">
{(props) =>
<ReloadIcon {...props} className="bd-icon bd-reload bd-reload-header" size="18px" onClick={async () => {
if (this.isPlugins) pluginModule.updatePluginList();
else themeModule.updateThemeList();
this.forceUpdate();
}} />
}</Tooltip>;
const addonCards = this.getAddons();
return <ContentColumn title={`${this.props.type.toUpperCase()}${addonCards.length}`}>
<button key="folder-button" className="bd-button bd-pfbtn" onClick={this.openFolder.bind(this)}>Open {this.isPlugins ? "Plugin" : "Theme"} Folder</button>
{this.renderCheckUpdates()}
{!settingsCookie["fork-ps-5"] && refreshIcon}
<div className="bd-controls bd-addon-controls">
<Search onChange={this.search} placeholder={`Search ${this.props.type}...`} />
<div className="bd-addon-dropdowns">
<div className="bd-select-wrapper">
<label className="bd-label">Sort by:</label>
<Dropdown options={this.sortOptions} onChange={this.sort} style="transparent" />
</div>
<div className="bd-select-wrapper">
<label className="bd-label">Order:</label>
<Dropdown options={this.directions} onChange={this.reverse} style="transparent" />
</div>
</div>
</div>
<div className="bda-slist bd-addon-list">{addonCards}</div>
</ContentColumn>
}
}
const originalRender = CardList.prototype.render;
Object.defineProperty(CardList.prototype, "render", {
enumerable: false,
configurable: false,
set: function() {console.warn("Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins");},
get: () => originalRender
import ErrorBoundary from "./errorBoundary";
import ContentColumn from "./contentColumn";
import Tools from "./tools";
import ReloadIcon from "./reloadIcon";
import AddonCard from "./addoncard";
import Scroller from "./scroller";
import Dropdown from "./components/dropdown";
import Search from "./components/search";
import {settingsCookie, pluginCookie, themeCookie} from "../0globals";
import ContentManager from "../modules/contentManager";
import BDV2 from "../modules/v2";
import pluginModule from "../modules/pluginModule";
import themeModule from "../modules/themeModule";
import WebpackModules from "../modules/webpackModules";
import BdApi from "../modules/bdApi";
import Utils from "../modules/utils";
import tooltipWrap from "./tooltipWrap";
const Tooltip = WebpackModules.findByDisplayName("Tooltip");
const React = BDV2.react;
export default class CardList extends BDV2.reactComponent {
constructor(props) {
super(props);
this.state = {sort: "name", ascending: true, query: ""};
this.isPlugins = this.props.type == "plugins";
this.cookie = this.isPlugins ? pluginCookie : themeCookie;
this.manager = this.isPlugins ? pluginModule : themeModule;
this.sort = this.sort.bind(this);
this.reverse = this.reverse.bind(this);
this.search = this.search.bind(this);
}
openFolder() {
require("electron").shell.openItem(this.isPlugins ? ContentManager.pluginsFolder : ContentManager.themesFolder);
}
edit(name) {
console.log(name);
this.manager.edit(name);
}
async delete(name) {
const shouldDelete = await this.confirmDelete(name);
if (!shouldDelete) return;
this.manager.delete(name);
}
confirmDelete(name) {
return new Promise(resolve => {
BdApi.showConfirmationModal("Are You Sure?", `Are you sure you want to delete ${name}?`, {
danger: true,
confirmText: "Delete",
onConfirm: () => {resolve(true);},
onCancel: () => {resolve(false);}
});
});
}
get sortOptions() {
return [
{label: "Name", value: "name"},
{label: "Author", value: "author"},
{label: "Version", value: "version"},
{label: "Recently Added", value: "added"},
{label: "Last Modified", value: "modified"},
{label: "File Size", value: "size"},
];
}
get directions() {
return [
{label: "Ascending", value: true},
{label: "Descending", value: false}
];
}
reverse(value) {
this.setState({ascending: value});
}
sort(value) {
this.setState({sort: value});
}
search(event) {
this.setState({query: event.target.value.toLocaleLowerCase()});
}
getProps(addon) {
return {
key: this.getName(addon),
enabled: this.cookie[this.getName(addon)],
toggle: this.manager.toggle.bind(this.manager),
edit: settingsCookie["fork-ps-7"] ? this.edit.bind(this) : null,
remove: this.delete.bind(this),
addon: addon,
hash: addon.hash
};
}
getString(value) {
if (!value) return "???";
return typeof value == "string" ? value : value.toString();
}
get list(){
return this.props.type === "plugins" ? Object.values(bdplugins) : Object.values(bdthemes);
}
getAddons() {
const sortedAddons = this.list.sort((a, b) => {
const cap = this.state.sort.charAt(0).toUpperCase() + this.state.sort.slice(1);
const first = a.plugin && a.plugin[`get${cap}`] ? this.getString(a.plugin[`get${cap}`]()) : a[this.state.sort];
const second = b.plugin && b.plugin[`get${cap}`] ? this.getString(b.plugin[`get${cap}`]()) : b[this.state.sort];
if (typeof(first) == "string") return first.toLocaleLowerCase().localeCompare(second.toLocaleLowerCase());
if (first > second) return 1;
if (second > first) return -1;
return 0;
});
if (!this.state.ascending) sortedAddons.reverse();
const rendered = [];
for (let a = 0; a < sortedAddons.length; a++) {
const addon = sortedAddons[a];
if (this.state.query) {
let matches = null;
const name = this.getName(addon);
const author = this.getAuthor(addon);
const description = this.getDescription(addon);
const version = this.getVersion(addon);
if (name) matches = name.toLocaleLowerCase().includes(this.state.query);
if (author) matches = matches || author.toLocaleLowerCase().includes(this.state.query);
if (description) matches = matches || description.toLocaleLowerCase().includes(this.state.query);
if (version) matches = matches || version.toLocaleLowerCase().includes(this.state.query);
if (!matches) continue;
}
const props = this.getProps(addon);
rendered.push(<ErrorBoundary><AddonCard {...props} reload={!settingsCookie["fork-ps-5"] && this.manager.reload.bind(this.manager)} /></ErrorBoundary>);
}
return rendered;
}
getName(addon) {return this.getString(addon.plugin ? addon.plugin.getName() : addon.name);}
getAuthor(addon) {return this.getString(addon.plugin ? addon.plugin.getAuthor() : addon.author);}
getDescription(addon) {return this.getString(addon.plugin ? addon.plugin.getDescription() : addon.description);}
getVersion(addon) {return this.getString(addon.plugin ? addon.plugin.getVersion() : addon.version);}
renderCheckUpdates(){
if(!window.ZeresPluginLibrary)return null
if(!window.PluginUpdates)return null
if(typeof window.PluginUpdates.checkAll !== "function")return null
if(!this.isPlugins)return null
return <tooltipWrap text="Checks for updates of plugins that support this feature. Right-click for a list.">
<span style={{marginLeft: "10px"}}>
<Lightcord.Api.Components.inputs.Button color="brand" look="filled" size="min" hoverColor="default" onClick={() => {
try{
Utils.showToast("Plugin update check in progress.", {type: "info"})
window.PluginUpdates.checkAll()
.then(() => {
Utils.showToast("Plugin update check complete.", {type: "success"})
}).catch(err => {
console.error(err)
Utils.showToast("An error occured while checking update.", {type: "error"})
})
}catch(e){
console.error(e)
Utils.showToast("An error occured while checking update.", {type: "error"})
}
}} wrapper={false} disabled={false}>
Check for Updates
</Lightcord.Api.Components.inputs.Button>
</span>
</tooltipWrap>
}
render() {
const refreshIcon = <Tooltip color="black" position="top" text="Reload List">
{(props) =>
<ReloadIcon {...props} className="bd-icon bd-reload bd-reload-header" size="18px" onClick={async () => {
if (this.isPlugins) pluginModule.updatePluginList();
else themeModule.updateThemeList();
this.forceUpdate();
}} />
}</Tooltip>;
const addonCards = this.getAddons();
return <ContentColumn title={`${this.props.type.toUpperCase()}${addonCards.length}`}>
<button key="folder-button" className="bd-button bd-pfbtn" onClick={this.openFolder.bind(this)}>Open {this.isPlugins ? "Plugin" : "Theme"} Folder</button>
{this.renderCheckUpdates()}
{!settingsCookie["fork-ps-5"] && refreshIcon}
<div className="bd-controls bd-addon-controls">
<Search onChange={this.search} placeholder={`Search ${this.props.type}...`} />
<div className="bd-addon-dropdowns">
<div className="bd-select-wrapper">
<label className="bd-label">Sort by:</label>
<Dropdown options={this.sortOptions} onChange={this.sort} style="transparent" />
</div>
<div className="bd-select-wrapper">
<label className="bd-label">Order:</label>
<Dropdown options={this.directions} onChange={this.reverse} style="transparent" />
</div>
</div>
</div>
<div className="bda-slist bd-addon-list">{addonCards}</div>
</ContentColumn>
}
}
const originalRender = CardList.prototype.render;
Object.defineProperty(CardList.prototype, "render", {
enumerable: false,
configurable: false,
set: function() {console.warn("Addon policy for plugins #5 https://github.com/rauenzi/BetterDiscordApp/wiki/Addon-Policies#plugins");},
get: () => originalRender
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long