diff --git a/assets/locales/en-us.json b/assets/locales/en-us.json
index 52f68164..e008f65c 100644
--- a/assets/locales/en-us.json
+++ b/assets/locales/en-us.json
@@ -257,6 +257,8 @@
"updateButton": "Update!"
},
"Settings": {
- "customColor": "Custom Color"
+ "customColor": "Custom Color",
+ "resetSettings": "Reset Settings",
+ "resetSettingsWarning": "Resetting your settings returns them all to the original state, this cannot be undone."
}
}
\ No newline at end of file
diff --git a/renderer/src/modules/settingsmanager.js b/renderer/src/modules/settingsmanager.js
index 63717a68..e5684604 100644
--- a/renderer/src/modules/settingsmanager.js
+++ b/renderer/src/modules/settingsmanager.js
@@ -73,12 +73,16 @@ export default new class SettingsManager {
if (!this.state[collection.id]) this.state[collection.id] = {};
for (let cc = 0; cc < categories.length; cc++) {
const category = categories[cc];
- if (category.type != "category") {if (!this.state[collection.id].hasOwnProperty(category.id)) this.state[collection.id][category.id] = category.value;}
+ if (category.type != "category") {
+ if (!this.state[collection.id].hasOwnProperty(category.id)) this.state[collection.id][category.id] = category.value;
+ category.defaultValue = category.value;
+ }
else {
if (!this.state[collection.id].hasOwnProperty(category.id)) this.state[collection.id][category.id] = {};
for (let s = 0; s < category.settings.length; s++) {
const setting = category.settings[s];
if (!this.state[collection.id][category.id].hasOwnProperty(setting.id)) this.state[collection.id][category.id][setting.id] = setting.value;
+ setting.defaultValue = setting.value;
if (setting.hasOwnProperty("disabled")) continue;
if (!setting.enableWith && !setting.disableWith) continue;
const pathString = setting.enableWith || setting.disableWith;
@@ -131,6 +135,28 @@ export default new class SettingsManager {
this.saveCollection(id); // in case new things were added
}
+ resetCollection(id) {
+ const collection = this.collections.find(c => c.id == id);
+ if (!collection) return;
+ const categories = collection.settings;
+ for (let cc = 0; cc < categories.length; cc++) {
+ const category = categories[cc];
+ if (category.type != "category") {
+ // console.log("cat", collection.id, category.id, this.get(collection.id, category.id), category.value);
+ if (this.get(collection.id, category.id) == category.defaultValue) continue;
+ this.set(collection.id, category.id, category.defaultValue);
+ }
+ else {
+ for (let s = 0; s < category.settings.length; s++) {
+ const setting = category.settings[s];
+ // console.log("setting", collection.id, category.id, setting.id, this.get(collection.id, category.id, setting.id), setting.defaultValue);
+ if (this.get(collection.id, category.id, setting.id) == setting.defaultValue) continue;
+ this.set(collection.id, category.id, setting.id, setting.defaultValue);
+ }
+ }
+ }
+ }
+
onSettingChange(collection, category, id, value) {
this.state[collection][category][id] = value;
Events.dispatch("setting-updated", collection, category, id, value);
diff --git a/renderer/src/ui/icons/restore.jsx b/renderer/src/ui/icons/restore.jsx
new file mode 100644
index 00000000..092cdd75
--- /dev/null
+++ b/renderer/src/ui/icons/restore.jsx
@@ -0,0 +1,9 @@
+import React from "@modules/react";
+
+export default function Restore(props) {
+ const size = props.size || "24px";
+ return ;
+}
diff --git a/renderer/src/ui/settings.js b/renderer/src/ui/settings.js
index c54d3c07..ca167511 100644
--- a/renderer/src/ui/settings.js
+++ b/renderer/src/ui/settings.js
@@ -1,15 +1,55 @@
import React from "@modules/react";
+import Strings from "@modules/strings";
import Utilities from "@modules/utilities";
import Events from "@modules/emitter";
import Settings from "@modules/settingsmanager";
import DataStore from "@modules/datastore";
import WebpackModules, {Filters} from "@modules/webpackmodules";
import Patcher from "@modules/patcher";
+import DiscordModules from "@modules/discordmodules";
-import AddonList from "./settings/addonlist";
-import SettingsGroup from "./settings/group";
-import SettingsTitle from "./settings/title";
-import Header from "./settings/sidebarheader";
+import ReactUtils from "@modules/api/reactutils";
+
+import Button from "@ui/base/button";
+import Modals from "@ui/modals";
+
+import AddonList from "@ui/settings/addonlist";
+import SettingsGroup from "@ui/settings/group";
+import SettingsTitle from "@ui/settings/title";
+import Header from "@ui/settings/sidebarheader";
+
+import Restore from "./icons/restore";
+// import SettingsPanel from "./settings/panel";
+
+
+function makeResetButton(collectionId, refresh) {
+ const action = confirmReset(() => {
+ Settings.resetCollection(collectionId);
+ refresh?.();
+ });
+ return
+ {(props) =>
+
+ }
+ ;
+}
+
+/**
+ * @param {function} action
+ * @returns
+ */
+function confirmReset(action) {
+ return () => {
+ Modals.showConfirmationModal(Strings.Modals.confirmAction, Strings.Settings.resetSettingsWarning, {
+ confirmText: Strings.Modals.okay,
+ cancelText: Strings.Modals.cancel,
+ danger: true,
+ onConfirm: action,
+ });
+ };
+}
export default new class SettingsRenderer {
@@ -34,22 +74,32 @@ export default new class SettingsRenderer {
onChange(onChange) {
return (collection, category, id) => {
- const before = Settings.collections.length + Settings.panels.length;
onChange(collection, category, id);
- const after = Settings.collections.length + Settings.panels.length;
- if (before != after) setTimeout(this.forceUpdate.bind(this), 50);
+
+ // Delay until after switch animation
+ // TODO: lift settings state to SettingsPanel
+ // to prevent the need for this.
+ setTimeout(this.forceUpdate.bind(this), 250);
};
}
- buildSettingsPanel(id, title, config, state, onChange, button = null) {
+ buildSettingsPanel(id, title, config, state, onChange) {
config.forEach(section => {
section.settings.forEach(item => item.value = state[section.id][item.id]);
});
- return this.getSettingsPanel(id, title, config, this.onChange(onChange), button);
+ return this.getSettingsPanel(id, title, config, this.onChange(onChange));
}
- getSettingsPanel(id, title, groups, onChange, button = null) {
- return [React.createElement(SettingsTitle, {text: title, button: button}), groups.map(section => {
+ getSettingsPanel(id, title, groups, onChange) {
+ // return this.onDrawerToggle(...args)}
+ // getDrawerState={(...args) => this.getDrawerState(...args)}
+ // />;
+ return [React.createElement(SettingsTitle, {text: title}, makeResetButton(id, this.forceUpdate.bind(this))), groups.map(section => {
return React.createElement(SettingsGroup, Object.assign({}, section, {
onChange: onChange,
onDrawerToggle: state => this.onDrawerToggle(id, section.id, state),
@@ -85,7 +135,7 @@ export default new class SettingsRenderer {
section: collection.name,
label: collection.name.toString(),
className: `bd-${collection.id}-tab`,
- element: () => this.buildSettingsPanel(collection.id, collection.name, collection.settings, Settings.state[collection.id], Settings.onSettingChange.bind(Settings, collection.id), collection.button ? collection.button : null)
+ element: () => this.buildSettingsPanel(collection.id, collection.name, collection.settings, Settings.state[collection.id], Settings.onSettingChange.bind(Settings, collection.id))
});
}
for (const panel of Settings.panels.sort((a,b) => a.order > b.order ? 1 : -1)) {
@@ -101,7 +151,7 @@ export default new class SettingsRenderer {
const viewClass = WebpackModules.getByProps("standardSidebarView")?.standardSidebarView.split(" ")[0];
const node = document.querySelector(`.${viewClass}`);
if (!node) return;
- const stateNode = Utilities.findInTree(node?.__reactFiber$, m => m && m.getPredicateSections, {walkable: ["return", "stateNode"]});
+ const stateNode = Utilities.findInTree(ReactUtils.getInternalInstance(node), m => m && m.getPredicateSections, {walkable: ["return", "stateNode"]});
if (stateNode) stateNode.forceUpdate();
}
};
\ No newline at end of file
diff --git a/renderer/src/ui/settings/panel.jsx b/renderer/src/ui/settings/panel.jsx
new file mode 100644
index 00000000..bc7c7080
--- /dev/null
+++ b/renderer/src/ui/settings/panel.jsx
@@ -0,0 +1,68 @@
+import React from "@modules/react";
+import Strings from "@modules/strings";
+import Utilities from "@modules/utilities";
+import Events from "@modules/emitter";
+import Settings from "@modules/settingsmanager";
+import DataStore from "@modules/datastore";
+import WebpackModules, {Filters} from "@modules/webpackmodules";
+import Patcher from "@modules/patcher";
+import DiscordModules from "@modules/discordmodules";
+
+import Button from "@ui/base/button";
+import Modals from "@ui/modals";
+
+import AddonList from "@ui/settings/addonlist";
+import SettingsGroup from "@ui/settings/group";
+import SettingsTitle from "@ui/settings/title";
+import Header from "@ui/settings/sidebarheader";
+
+import Restore from "@ui/icons/restore";
+
+
+const {useCallback, useEffect, useReducer} = React;
+
+function makeResetButton(collectionId) {
+ const action = confirmReset(() => Settings.resetCollection(collectionId));
+ return
+ {(props) =>
+
+ }
+ ;
+}
+
+/**
+ * @param {function} action
+ * @returns
+ */
+function confirmReset(action) {
+ return () => {
+ Modals.showConfirmationModal(Strings.Modals.confirmAction, Strings.Settings.resetSettingsWarning, {
+ confirmText: Strings.Modals.okay,
+ cancelText: Strings.Modals.cancel,
+ danger: true,
+ onConfirm: action,
+ });
+ };
+}
+
+export default function SettingsPanel({id, title, groups, onChange, onDrawerToggle, getDrawerState}) {
+
+ // TODO: add onChange here to lift and manage state here
+
+ return <>
+
+ {makeResetButton(id)}
+ ,
+ {groups.map(section => {
+ const props = Object.assign({}, section, {
+ onChange,
+ onDrawerToggle: state => onDrawerToggle(id, section.id, state),
+ shown: getDrawerState(id, section.id, section.hasOwnProperty("shown") ? section.shown : true)
+ });
+ return ;
+ })}
+ >;
+
+}
\ No newline at end of file