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": {
"build": "webpack --progress --colors",
"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",
"minify": "gulp minify-css",
"watch-css": "gulp watch-css"

View File

@ -7,6 +7,7 @@ import ThemeManager from "./modules/thememanager";
import {bdPluginStorage} from "./modules/oldstorage";
import Events from "./modules/emitter";
import Settings from "./modules/settingsmanager";
import DataStore from "./modules/datastore";
import EmoteModule from "./builtins/emotes";
// Perform some setup
@ -30,6 +31,7 @@ window.bdEmotes = EmoteModule.Emotes;
window.bemotes = EmoteModule.blacklist;
window.bdPluginStorage = bdPluginStorage;
window.settingsModule = Settings;
window.DataStore = DataStore;
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
loadContent(filename, shouldToast = true) {
loadContent(filename, shouldToast = false) {
if (typeof(filename) === "undefined") return;
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});}
@ -162,10 +162,10 @@ export default class ContentManager {
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;
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))];
this.contentList.splice(this.contentList.indexOf(content), 1);
this.emit("unloaded", content.id);
@ -173,10 +173,11 @@ export default class ContentManager {
return true;
}
reloadContent(filename) {
const didUnload = this.unloadContent(filename);
reloadContent(idOrFileOrContent, shouldToast = true) {
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;
return this.loadContent(filename);
return this.loadContent(content.filename, shouldToast);
}
isLoaded(idOrFile) {

View File

@ -40,15 +40,21 @@ export default new class PluginManager extends ContentManager {
if (error) Modals.showContentErrors({themes: [error]});
}
reloadPlugin(filename) {
const error = this.reloadContent(filename);
if (error) Modals.showContentErrors({themes: [error]});
reloadPlugin(idOrFileOrContent) {
const error = this.reloadContent(idOrFileOrContent);
if (error) Modals.showContentErrors({plugins: [error]});
return typeof(idOrFileOrContent) == "string" ? this.contentList.find(c => c.id == idOrFileOrContent || c.filename == idOrFileOrContent) : idOrFileOrContent;
}
loadAllPlugins() {
const errors = this.loadAllContent();
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;
}
@ -59,9 +65,9 @@ export default new class PluginManager extends ContentManager {
const thePlugin = new content.type();
content.plugin = thePlugin;
content.name = thePlugin.getName() || content.name;
content.author = content.author || thePlugin.getAuthor() || "No author";
content.description = content.description || thePlugin.getDescription() || "No description";
content.version = content.version || thePlugin.getVersion() || "No version";
content.author = thePlugin.getAuthor() || content.author || "No author";
content.description = thePlugin.getDescription() || content.description || "No description";
content.version = thePlugin.getVersion() || content.version || "No version";
try {
if (typeof(content.plugin.load) == "function") content.plugin.load();
}

View File

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

View File

@ -17,7 +17,12 @@ export default new class ThemeManager extends ContentManager {
/* Aliases */
updateThemeList() {return this.updateList();}
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();
}
@ -32,8 +37,8 @@ export default new class ThemeManager extends ContentManager {
if (error) Modals.showContentErrors({themes: [error]});
}
reloadTheme(filename) {
const error = this.reloadContent(filename);
reloadTheme(idOrFileOrContent) {
const error = this.reloadContent(idOrFileOrContent);
if (error) Modals.showContentErrors({themes: [error]});
}

View File

@ -1,4 +1,3 @@
import {SettingsState} from "data";
import Utilities from "../modules/utilities";
import Events from "../modules/emitter";
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 {React, Utilities, PluginManager} from "modules";
import {React, Utilities, Settings} from "modules";
import CloseButton from "../icons/close";
// import ReloadIcon from "../icons/reload";
import ReloadIcon from "../icons/reload";
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.showSettings = this.showSettings.bind(this);
this.state = {
checked: PluginManager.isEnabled(this.props.content.id),
settings: false
checked: this.props.enabled,//PluginManager.isEnabled(this.props.content.id),
settingsOpen: false
};
this.hasSettings = typeof this.props.content.plugin.getSettingsPanel === "function";
this.settingsPanel = "";
this.panelRef = React.createRef();
// this.reload = this.reload.bind(this);
this.reload = this.reload.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() {
if (this.state.settings) {
if (typeof this.settingsPanel === "object") {
if (this.state.settingsOpen) {
if (this.settingsPanel instanceof Node) {
this.panelRef.current.appendChild(this.settingsPanel);
}
@ -62,20 +68,22 @@ export default class V2C_PluginCard extends React.Component {
const website = content.website;
const source = content.source;
if (this.state.settings) {
if (this.state.settingsOpen) {
try { self.settingsPanel = content.plugin.getSettingsPanel(); }
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"},
React.createElement("div", {style: {"float": "right", "cursor": "pointer"}, onClick: () => {
this.panelRef.current.innerHTML = "";
self.setState({settings: false});
self.setState({settingsOpen: false});
}},
React.createElement(CloseButton, null)
),
typeof self.settingsPanel === "object" && React.createElement("div", {id: `plugin-settings-${name}`, className: "plugin-settings", ref: this.panelRef}),
typeof self.settingsPanel !== "object" && React.createElement("div", {id: `plugin-settings-${name}`, className: "plugin-settings", ref: this.panelRef, dangerouslySetInnerHTML: {__html: self.settingsPanel}})
);
React.createElement("div", props, this.settingsPanel instanceof React.Component ? this.settingsPanel : null),
);
}
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("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("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"})
@ -111,11 +119,12 @@ export default class V2C_PluginCard extends React.Component {
onChange() {
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() {
if (!this.hasSettings) return;
this.setState({settings: true});
this.setState({settingsOpen: true});
}
}

View File

@ -1,9 +1,7 @@
import {Config} from "data";
import {React} from "modules";
import PluginCard from "./plugincard";
import ThemeCard from "./themecard";
import ContentList from "./contentlist";
import SettingsGroup from "../settings/group";
import SettingsTitle from "./title";
@ -22,20 +20,12 @@ export default class V2_SettingsPanel {
})];
}
static getPluginsPanel(plugins, folder) {
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, content: plugin})
);
return [titleComponent, React.createElement("ul", {className: "bda-slist"}, ...cards)];
}
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 getContentPanel(title, contentList, contentState, options = {}) {
return React.createElement(ContentList, Object.assign({}, {
title: title,
contentList: contentList,
contentState: contentState
}, options));
}
static get attribution() {

View File

@ -1,5 +1,5 @@
import {React, ThemeManager} from "modules";
// import ReloadIcon from "../icons/reload";
import {React, Settings} from "modules";
import ReloadIcon from "../icons/reload";
// import Toasts from "../toasts";
export default class V2C_ThemeCard extends React.Component {
@ -7,27 +7,18 @@ export default class V2C_ThemeCard extends React.Component {
constructor(props) {
super(props);
this.state = {
checked: ThemeManager.isEnabled(this.props.content.id),
checked: this.props.enabled, //ThemeManager.isEnabled(this.props.content.id),
reloads: 0
};
this.onChange = this.onChange.bind(this);
// this.reload = this.reload.bind(this);
this.reload = this.reload.bind(this);
}
// onReload(themeName) {
// if (themeName !== this.props.theme.name) return;
// this.setState({reloads: this.state.reloads + 1});
// }
// 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);
// }
reload() {
if (!this.props.reload) return;
this.props.content = this.props.reload(this.props.content.id);
this.forceUpdate();
}
render() {
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("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("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"})
@ -70,6 +61,6 @@ export default class V2C_ThemeCard extends React.Component {
onChange() {
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();}}>
{this.props.text}
{this.props.button && <button className="bd-title-button" onClick={this.props.button.onClick}>{this.props.button.title}</button>}
{this.props.otherChildren}
</h2>;
}
}