1
0
mirror of https://github.com/rauenzi/BetterDiscordApp.git synced 2025-04-11 22:57:35 +02:00

fix settings stuff, content list panels

This commit is contained in:
Zack Rauen 2019-06-09 18:37:46 -04:00
parent 869c4c5b71
commit d365999efe
14 changed files with 155 additions and 91 deletions

File diff suppressed because one or more lines are too long

4
js/main.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"build": "webpack --progress --colors", "build": "webpack --progress --colors",
"watch": "webpack --progress --colors --watch", "watch": "webpack --progress --colors --watch",
"build-prod": "webpack --progress --colors --mode production -o js/main.min.js", "build-prod": "webpack --progress --colors --mode production -o js/main.min.js --devtool none",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"minify": "gulp minify-css", "minify": "gulp minify-css",
"watch-css": "gulp watch-css" "watch-css": "gulp watch-css"

View File

@ -7,6 +7,7 @@ import ThemeManager from "./modules/thememanager";
import {bdPluginStorage} from "./modules/oldstorage"; import {bdPluginStorage} from "./modules/oldstorage";
import Events from "./modules/emitter"; import Events from "./modules/emitter";
import Settings from "./modules/settingsmanager"; import Settings from "./modules/settingsmanager";
import DataStore from "./modules/datastore";
import EmoteModule from "./builtins/emotes"; import EmoteModule from "./builtins/emotes";
// Perform some setup // Perform some setup
@ -30,6 +31,7 @@ window.bdEmotes = EmoteModule.Emotes;
window.bemotes = EmoteModule.blacklist; window.bemotes = EmoteModule.blacklist;
window.bdPluginStorage = bdPluginStorage; window.bdPluginStorage = bdPluginStorage;
window.settingsModule = Settings; window.settingsModule = Settings;
window.DataStore = DataStore;
window.BDEvents = Events; window.BDEvents = Events;

View File

@ -146,7 +146,7 @@ export default class ContentManager {
} }
// Subclasses should use the return (if not ContentError) and push to this.contentList // Subclasses should use the return (if not ContentError) and push to this.contentList
loadContent(filename, shouldToast = true) { loadContent(filename, shouldToast = false) {
if (typeof(filename) === "undefined") return; if (typeof(filename) === "undefined") return;
try {__non_webpack_require__(path.resolve(this.contentFolder, filename));} try {__non_webpack_require__(path.resolve(this.contentFolder, filename));}
catch (error) {return new ContentError(filename, filename, "Could not be compiled.", {message: error.message, stack: error.stack});} catch (error) {return new ContentError(filename, filename, "Could not be compiled.", {message: error.message, stack: error.stack});}
@ -162,10 +162,10 @@ export default class ContentManager {
return this.startContent(content); return this.startContent(content);
} }
unloadContent(idOrFileOrContent, shouldToast = true) { unloadContent(idOrFileOrContent, shouldToast = true, isReload = false) {
const content = typeof(idOrFileOrContent) == "string" ? this.contentList.find(c => c.id == idOrFileOrContent || c.filename == idOrFileOrContent) : idOrFileOrContent; const content = typeof(idOrFileOrContent) == "string" ? this.contentList.find(c => c.id == idOrFileOrContent || c.filename == idOrFileOrContent) : idOrFileOrContent;
if (!content) return false; if (!content) return false;
if (this.state[content.id]) this.disableContent(content); if (this.state[content.id]) isReload ? this.stopContent(content) : this.disableContent(content);
delete __non_webpack_require__.cache[__non_webpack_require__.resolve(path.resolve(this.contentFolder, content.filename))]; delete __non_webpack_require__.cache[__non_webpack_require__.resolve(path.resolve(this.contentFolder, content.filename))];
this.contentList.splice(this.contentList.indexOf(content), 1); this.contentList.splice(this.contentList.indexOf(content), 1);
this.emit("unloaded", content.id); this.emit("unloaded", content.id);
@ -173,10 +173,11 @@ export default class ContentManager {
return true; return true;
} }
reloadContent(filename) { reloadContent(idOrFileOrContent, shouldToast = true) {
const didUnload = this.unloadContent(filename); const content = typeof(idOrFileOrContent) == "string" ? this.contentList.find(c => c.id == idOrFileOrContent || c.filename == idOrFileOrContent) : idOrFileOrContent;
const didUnload = this.unloadContent(content, shouldToast, true);
if (!didUnload) return didUnload; if (!didUnload) return didUnload;
return this.loadContent(filename); return this.loadContent(content.filename, shouldToast);
} }
isLoaded(idOrFile) { isLoaded(idOrFile) {

View File

@ -40,15 +40,21 @@ export default new class PluginManager extends ContentManager {
if (error) Modals.showContentErrors({themes: [error]}); if (error) Modals.showContentErrors({themes: [error]});
} }
reloadPlugin(filename) { reloadPlugin(idOrFileOrContent) {
const error = this.reloadContent(filename); const error = this.reloadContent(idOrFileOrContent);
if (error) Modals.showContentErrors({themes: [error]}); if (error) Modals.showContentErrors({plugins: [error]});
return typeof(idOrFileOrContent) == "string" ? this.contentList.find(c => c.id == idOrFileOrContent || c.filename == idOrFileOrContent) : idOrFileOrContent;
} }
loadAllPlugins() { loadAllPlugins() {
const errors = this.loadAllContent(); const errors = this.loadAllContent();
this.setupFunctions(); this.setupFunctions();
Settings.registerPanel("Plugins", {element: () => SettingsRenderer.getPluginsPanel(this.contentList, this.contentFolder)}); Settings.registerPanel("Plugins", {element: () => SettingsRenderer.getContentPanel("Plugins", this.contentList, this.state, {
folder: this.contentFolder,
onChange: this.togglePlugin.bind(this),
reload: this.reloadPlugin.bind(this),
refreshList: this.updatePluginList.bind(this)
})});
return errors; return errors;
} }
@ -59,9 +65,9 @@ export default new class PluginManager extends ContentManager {
const thePlugin = new content.type(); const thePlugin = new content.type();
content.plugin = thePlugin; content.plugin = thePlugin;
content.name = thePlugin.getName() || content.name; content.name = thePlugin.getName() || content.name;
content.author = content.author || thePlugin.getAuthor() || "No author"; content.author = thePlugin.getAuthor() || content.author || "No author";
content.description = content.description || thePlugin.getDescription() || "No description"; content.description = thePlugin.getDescription() || content.description || "No description";
content.version = content.version || thePlugin.getVersion() || "No version"; content.version = thePlugin.getVersion() || content.version || "No version";
try { try {
if (typeof(content.plugin.load) == "function") content.plugin.load(); if (typeof(content.plugin.load) == "function") content.plugin.load();
} }

View File

@ -58,8 +58,6 @@ export default new class SettingsManager {
} }
setup() { setup() {
console.log("before state");
console.log(this.state);
for (let c = 0; c < this.collections.length; c++) { for (let c = 0; c < this.collections.length; c++) {
const collection = this.collections[c]; const collection = this.collections[c];
const categories = this.collections[c].settings; const categories = this.collections[c].settings;
@ -93,8 +91,6 @@ export default new class SettingsManager {
}); });
} }
} }
console.log("after state");
console.log(this.state);
} }
async patchSections() { async patchSections() {
@ -145,12 +141,12 @@ export default new class SettingsManager {
loadSettings() { loadSettings() {
const previousState = DataStore.getData("settings"); const previousState = DataStore.getData("settings");
if (!previousState) return this.saveSettings(); if (!previousState) return this.saveSettings();
for (const collection in this.defaultState) { for (const collection in this.state) {
if (!previousState[collection]) Object.assign(previousState, {[collection]: this.defaultState[collection]}); if (!previousState[collection]) Object.assign(previousState, {[collection]: this.state[collection]});
for (const category in this.defaultState[collection]) { for (const category in this.state[collection]) {
if (!previousState[collection][category]) Object.assign(previousState[collection][category], {[category]: this.defaultState[collection][category]}); if (!previousState[collection][category]) Object.assign(previousState[collection][category], {[category]: this.state[collection][category]});
for (const setting in this.defaultState[collection][category]) { for (const setting in this.state[collection][category]) {
if (previousState[collection][category][setting] == undefined) continue; if (previousState[collection][category][setting] == undefined) continue;
this.state[collection][category][setting] = previousState[collection][category][setting]; this.state[collection][category][setting] = previousState[collection][category][setting];
} }

View File

@ -17,7 +17,12 @@ export default new class ThemeManager extends ContentManager {
/* Aliases */ /* Aliases */
updateThemeList() {return this.updateList();} updateThemeList() {return this.updateList();}
loadAllThemes() { loadAllThemes() {
Settings.registerPanel("Themes", {element: () => SettingsRenderer.getThemesPanel(this.contentList, this.contentFolder)}); Settings.registerPanel("Themes", {element: () => SettingsRenderer.getContentPanel("Themes", this.contentList, this.state, {
folder: this.contentFolder,
onChange: this.toggleTheme.bind(this),
reload: this.reloadTheme.bind(this),
refreshList: this.updateThemeList.bind(this)
})});
return this.loadAllContent(); return this.loadAllContent();
} }
@ -32,8 +37,8 @@ export default new class ThemeManager extends ContentManager {
if (error) Modals.showContentErrors({themes: [error]}); if (error) Modals.showContentErrors({themes: [error]});
} }
reloadTheme(filename) { reloadTheme(idOrFileOrContent) {
const error = this.reloadContent(filename); const error = this.reloadContent(idOrFileOrContent);
if (error) Modals.showContentErrors({themes: [error]}); if (error) Modals.showContentErrors({themes: [error]});
} }

View File

@ -1,4 +1,3 @@
import {SettingsState} from "data";
import Utilities from "../modules/utilities"; import Utilities from "../modules/utilities";
import Events from "../modules/emitter"; import Events from "../modules/emitter";
import Settings from "../modules/settingsmanager"; import Settings from "../modules/settingsmanager";

View File

@ -0,0 +1,38 @@
// static getPluginsPanel(plugins, state, options = {}) {
// const {folder = "", onChange, reload} = options;
// const titleComponent = React.createElement(SettingsTitle, {text: "Plugins", button: {title: "Open Plugin Folder", onClick: () => { require("electron").shell.openItem(folder); }}});
// const cards = plugins.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).map(plugin =>
// React.createElement(PluginCard, {key: plugin.id, enabled: state[plugin.id], content: plugin, onChange, reload})
// );
// return [titleComponent, React.createElement("ul", {className: "bda-slist"}, ...cards)];
// }
import {React, Settings} from "modules";
import SettingsTitle from "./title";
import PluginCard from "./plugincard";
import ThemeCard from "./themecard";
import ReloadIcon from "../icons/reload";
export default class ContentList extends React.Component {
reload() {
if (this.props.refreshList) this.props.refreshList();
this.forceUpdate();
}
render() {
const {title, folder, contentList, contentState, onChange, reload} = this.props;
const showReloadIcon = !Settings.get("settings", "content", "autoReload");
const button = folder ? {title: `Open ${title} Folder`, onClick: () => {require("electron").shell.openItem(folder);}} : null;
return [
<SettingsTitle key="title" text={title} button={button} otherChildren={showReloadIcon && <ReloadIcon onClick={this.reload.bind(this)} />} />,
<ul key="ContentList" className={"bda-slist"}>
{contentList.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).map(content => {
const CardType = content.type ? PluginCard : ThemeCard;
return <CardType showReloadIcon={showReloadIcon} key={content.id} enabled={contentState[content.id]} content={content} onChange={onChange} reload={reload} />;
})}
</ul>
];
}
}

View File

@ -1,7 +1,7 @@
// import {SettingsCookie, PluginCookie, Plugins} from "data"; // import {SettingsCookie, PluginCookie, Plugins} from "data";
import {React, Utilities, PluginManager} from "modules"; import {React, Utilities, Settings} from "modules";
import CloseButton from "../icons/close"; import CloseButton from "../icons/close";
// import ReloadIcon from "../icons/reload"; import ReloadIcon from "../icons/reload";
export default class V2C_PluginCard extends React.Component { export default class V2C_PluginCard extends React.Component {
@ -10,20 +10,26 @@ export default class V2C_PluginCard extends React.Component {
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
this.showSettings = this.showSettings.bind(this); this.showSettings = this.showSettings.bind(this);
this.state = { this.state = {
checked: PluginManager.isEnabled(this.props.content.id), checked: this.props.enabled,//PluginManager.isEnabled(this.props.content.id),
settings: false settingsOpen: false
}; };
this.hasSettings = typeof this.props.content.plugin.getSettingsPanel === "function"; this.hasSettings = typeof this.props.content.plugin.getSettingsPanel === "function";
this.settingsPanel = ""; this.settingsPanel = "";
this.panelRef = React.createRef(); this.panelRef = React.createRef();
// this.reload = this.reload.bind(this); this.reload = this.reload.bind(this);
// this.onReload = this.onReload.bind(this); // this.onReload = this.onReload.bind(this);
} }
reload() {
if (!this.props.reload) return;
this.props.content = this.props.reload(this.props.content.id);
this.forceUpdate();
}
componentDidUpdate() { componentDidUpdate() {
if (this.state.settings) { if (this.state.settingsOpen) {
if (typeof this.settingsPanel === "object") { if (this.settingsPanel instanceof Node) {
this.panelRef.current.appendChild(this.settingsPanel); this.panelRef.current.appendChild(this.settingsPanel);
} }
@ -62,20 +68,22 @@ export default class V2C_PluginCard extends React.Component {
const website = content.website; const website = content.website;
const source = content.source; const source = content.source;
if (this.state.settings) { if (this.state.settingsOpen) {
try { self.settingsPanel = content.plugin.getSettingsPanel(); } try { self.settingsPanel = content.plugin.getSettingsPanel(); }
catch (err) { Utilities.err("Plugins", "Unable to get settings panel for " + content.name + ".", err); } catch (err) { Utilities.err("Plugins", "Unable to get settings panel for " + content.name + ".", err); }
const props = {id: `plugin-settings-${name}`, className: "plugin-settings", ref: this.panelRef};
if (typeof(this.settingsPanel) == "string") props.dangerouslySetInnerHTML = this.settingsPanel;
return React.createElement("li", {className: "settings-open ui-switch-item"}, return React.createElement("li", {className: "settings-open ui-switch-item"},
React.createElement("div", {style: {"float": "right", "cursor": "pointer"}, onClick: () => { React.createElement("div", {style: {"float": "right", "cursor": "pointer"}, onClick: () => {
this.panelRef.current.innerHTML = ""; this.panelRef.current.innerHTML = "";
self.setState({settings: false}); self.setState({settingsOpen: false});
}}, }},
React.createElement(CloseButton, null) React.createElement(CloseButton, null)
), ),
typeof self.settingsPanel === "object" && React.createElement("div", {id: `plugin-settings-${name}`, className: "plugin-settings", ref: this.panelRef}), React.createElement("div", props, this.settingsPanel instanceof React.Component ? this.settingsPanel : null),
typeof self.settingsPanel !== "object" && React.createElement("div", {id: `plugin-settings-${name}`, className: "plugin-settings", ref: this.panelRef, dangerouslySetInnerHTML: {__html: self.settingsPanel}}) );
);
} }
return React.createElement("li", {"data-name": name, "data-version": version, "className": "settings-closed ui-switch-item"}, return React.createElement("li", {"data-name": name, "data-version": version, "className": "settings-closed ui-switch-item"},
@ -88,7 +96,7 @@ export default class V2C_PluginCard extends React.Component {
React.createElement("span", {className: "bda-author"}, author) React.createElement("span", {className: "bda-author"}, author)
), ),
React.createElement("div", {className: "bda-controls"}, React.createElement("div", {className: "bda-controls"},
//!SettingsCookie["fork-ps-5"] && React.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}), !Settings.get("settings", "content", "autoReload") && React.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
React.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}}, React.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
React.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}), React.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}),
React.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"}) React.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"})
@ -111,11 +119,12 @@ export default class V2C_PluginCard extends React.Component {
onChange() { onChange() {
this.setState({checked: !this.state.checked}); this.setState({checked: !this.state.checked});
PluginManager.togglePlugin(this.props.content.id); // PluginManager.togglePlugin(this.props.content.id);
this.props.onChange && this.props.onChange(this.props.content.id);
} }
showSettings() { showSettings() {
if (!this.hasSettings) return; if (!this.hasSettings) return;
this.setState({settings: true}); this.setState({settingsOpen: true});
} }
} }

View File

@ -1,9 +1,7 @@
import {Config} from "data"; import {Config} from "data";
import {React} from "modules"; import {React} from "modules";
import PluginCard from "./plugincard"; import ContentList from "./contentlist";
import ThemeCard from "./themecard";
import SettingsGroup from "../settings/group"; import SettingsGroup from "../settings/group";
import SettingsTitle from "./title"; import SettingsTitle from "./title";
@ -22,20 +20,12 @@ export default class V2_SettingsPanel {
})]; })];
} }
static getPluginsPanel(plugins, folder) { static getContentPanel(title, contentList, contentState, options = {}) {
const titleComponent = React.createElement(SettingsTitle, {text: "Plugins", button: {title: "Open Plugin Folder", onClick: () => { require("electron").shell.openItem(folder); }}}); return React.createElement(ContentList, Object.assign({}, {
const cards = plugins.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).map(plugin => title: title,
React.createElement(PluginCard, {key: plugin.id, content: plugin}) contentList: contentList,
); contentState: contentState
return [titleComponent, React.createElement("ul", {className: "bda-slist"}, ...cards)]; }, options));
}
static getThemesPanel(themes, folder) {
const titleComponent = React.createElement(SettingsTitle, {text: "Themes", button: {title: "Open Theme Folder", onClick: () => { require("electron").shell.openItem(folder); }}});
const cards = themes.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).map(theme =>
React.createElement(ThemeCard, {key: theme.id, content: theme})
);
return [titleComponent, React.createElement("ul", {className: "bda-slist"}, ...cards)];
} }
static get attribution() { static get attribution() {

View File

@ -1,5 +1,5 @@
import {React, ThemeManager} from "modules"; import {React, Settings} from "modules";
// import ReloadIcon from "../icons/reload"; import ReloadIcon from "../icons/reload";
// import Toasts from "../toasts"; // import Toasts from "../toasts";
export default class V2C_ThemeCard extends React.Component { export default class V2C_ThemeCard extends React.Component {
@ -7,27 +7,18 @@ export default class V2C_ThemeCard extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
checked: ThemeManager.isEnabled(this.props.content.id), checked: this.props.enabled, //ThemeManager.isEnabled(this.props.content.id),
reloads: 0 reloads: 0
}; };
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
// this.reload = this.reload.bind(this); this.reload = this.reload.bind(this);
} }
// onReload(themeName) { reload() {
// if (themeName !== this.props.theme.name) return; if (!this.props.reload) return;
// this.setState({reloads: this.state.reloads + 1}); this.props.content = this.props.reload(this.props.content.id);
// } this.forceUpdate();
}
// reload() {
// const theme = this.props.theme.name;
// const error = ThemeManager.reloadTheme(theme);
// if (error) Toasts.show(`Could not reload ${Themes[theme].name}. Check console for details.`, {type: "error"});
// else Toasts.show(`${Themes[theme].name} v${Themes[theme].version} has been reloaded.`, {type: "success"});
// // this.setState(this.state);
// this.props.theme = Themes[theme];
// this.onReload(this.props.theme.name);
// }
render() { render() {
const {content} = this.props; const {content} = this.props;
@ -48,7 +39,7 @@ export default class V2C_ThemeCard extends React.Component {
React.createElement("span", {className: "bda-author"}, author) React.createElement("span", {className: "bda-author"}, author)
), ),
React.createElement("div", {className: "bda-controls"}, React.createElement("div", {className: "bda-controls"},
//!SettingsCookie["fork-ps-5"] && React.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}), !Settings.get("settings", "content", "autoReload") && React.createElement(ReloadIcon, {className: "bd-reload-card", onClick: this.reload}),
React.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}}, React.createElement("label", {className: "ui-switch-wrapper ui-flex-child", style: {flex: "0 0 auto"}},
React.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}), React.createElement("input", {checked: this.state.checked, onChange: this.onChange, className: "ui-switch-checkbox", type: "checkbox"}),
React.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"}) React.createElement("div", {className: this.state.checked ? "ui-switch checked" : "ui-switch"})
@ -70,6 +61,6 @@ export default class V2C_ThemeCard extends React.Component {
onChange() { onChange() {
this.setState({checked: !this.state.checked}); this.setState({checked: !this.state.checked});
ThemeManager.toggleTheme(this.props.content.id); this.props.onChange && this.props.onChange(this.props.content.id);
} }
} }

View File

@ -14,6 +14,7 @@ export default class SettingsTitle extends React.Component {
return <h2 className={titleClass} onClick={() => {this.props.onClick && this.props.onClick();}}> return <h2 className={titleClass} onClick={() => {this.props.onClick && this.props.onClick();}}>
{this.props.text} {this.props.text}
{this.props.button && <button className="bd-title-button" onClick={this.props.button.onClick}>{this.props.button.title}</button>} {this.props.button && <button className="bd-title-button" onClick={this.props.button.onClick}>{this.props.button.title}</button>}
{this.props.otherChildren}
</h2>; </h2>;
} }
} }