diff --git a/renderer/src/ui/settings/addoncard.jsx b/renderer/src/ui/settings/addoncard.jsx
index 8604944b..990b36dd 100644
--- a/renderer/src/ui/settings/addoncard.jsx
+++ b/renderer/src/ui/settings/addoncard.jsx
@@ -17,6 +17,9 @@ import ThemeIcon from "../icons/theme";
import Modals from "../modals";
import Toasts from "../toasts";
+const {useState, useCallback, useMemo} = React;
+
+
const LinkIcons = {
website: WebIcon,
source: GitHubIcon,
@@ -27,168 +30,128 @@ const LinkIcons = {
const LayerManager = {
pushLayer(component) {
- DiscordModules.Dispatcher.dispatch({
- type: "LAYER_PUSH",
- component
- });
+ DiscordModules.Dispatcher.dispatch({
+ type: "LAYER_PUSH",
+ component
+ });
},
popLayer() {
- DiscordModules.Dispatcher.dispatch({
- type: "LAYER_POP"
- });
+ DiscordModules.Dispatcher.dispatch({
+ type: "LAYER_POP"
+ });
},
popAllLayers() {
- DiscordModules.Dispatcher.dispatch({
- type: "LAYER_POP_ALL"
- });
+ DiscordModules.Dispatcher.dispatch({
+ type: "LAYER_POP_ALL"
+ });
}
- };
+};
+
const UserStore = WebpackModules.getByProps("getCurrentUser");
const ChannelStore = WebpackModules.getByProps("getDMFromUserId");
const PrivateChannelActions = WebpackModules.getByProps("openPrivateChannel");
const ChannelActions = WebpackModules.getByProps("selectPrivateChannel");
+const getString = value => typeof value == "string" ? value : value.toString();
-export default class AddonCard extends React.Component {
+function makeButton(title, children, action, {isControl = false, danger = false, disabled = false} = {}) {
+ const ButtonType = isControl ? "button" : "div";
+ return
+ {(props) => {
+ return {children};
+ }}
+ ;
+}
- constructor(props) {
- super(props);
-
- this.settingsPanel = "";
- this.panelRef = React.createRef();
-
- this.onChange = this.onChange.bind(this);
- this.showSettings = this.showSettings.bind(this);
- this.messageAuthor = this.messageAuthor.bind(this);
+function buildLink(type, url) {
+ if (!url) return null;
+ const icon = React.createElement(LinkIcons[type]);
+ const link = {icon};
+ if (type == "invite") {
+ link.props.onClick = function(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ let code = url;
+ const tester = /\.gg\/(.*)$/;
+ if (tester.test(code)) code = code.match(tester)[1];
+ LayerManager.popLayer();
+ DiscordModules.InviteActions?.acceptInviteAndTransitionToInviteChannel({inviteKey: code});
+ };
}
+ return makeButton(Strings.Addons[type], link);
+}
- showSettings() {
- if (!this.props.hasSettings || !this.props.enabled) return;
- const name = this.getString(this.props.addon.name);
+export default function AddonCard({addon, type, disabled, enabled, onChange: parentChange, hasSettings, editAddon, deleteAddon, getSettingsPanel}) {
+ const [isEnabled, setEnabled] = useState(enabled);
+ const onChange = useCallback(() => {
+ setEnabled(!isEnabled);
+ if (parentChange) parentChange(addon.id);
+ }, []);
+
+ const showSettings = useCallback(() => {
+ if (!hasSettings || !enabled) return;
+ const name = getString(addon.name);
try {
- Modals.showAddonSettingsModal(name, this.props.getSettingsPanel());
+ Modals.showAddonSettingsModal(name, getSettingsPanel());
}
catch (err) {
Toasts.show(Strings.Addons.settingsError.format({name}), {type: "error"});
Logger.stacktrace("Addon Settings", "Unable to get settings panel for " + name + ".", err);
}
- }
+ }, [hasSettings, enabled]);
- getString(value) {return typeof value == "string" ? value : value.toString();}
-
- onChange() {
- this.props.onChange && this.props.onChange(this.props.addon.id);
- this.props.enabled = !this.props.enabled;
- this.forceUpdate();
- }
-
- messageAuthor() {
- if (!this.props.addon.authorId) return;
+ const messageAuthor = useCallback(() => {
+ if (!addon.authorId) return;
if (LayerManager) LayerManager.popLayer();
if (!UserStore || !ChannelActions || !ChannelStore || !PrivateChannelActions) return;
const selfId = UserStore.getCurrentUser().id;
- if (selfId == this.props.addon.authorId) return;
- const privateChannelId = ChannelStore.getDMFromUserId(this.props.addon.authorId);
+ if (selfId == addon.authorId) return;
+ const privateChannelId = ChannelStore.getDMFromUserId(addon.authorId);
if (privateChannelId) return ChannelActions.selectPrivateChannel(privateChannelId);
- PrivateChannelActions.openPrivateChannel(selfId, this.props.addon.authorId);
- }
+ PrivateChannelActions.openPrivateChannel(selfId, addon.authorId);
+ }, [addon.authorId]);
- buildTitle(name, version, author) {
+
+ const title = useMemo(() => {
const authorArray = Strings.Addons.byline.split(/({{[A-Za-z]+}})/);
- const authorComponent = author.link || author.id
- ? {author.name}
- : {author.name};
+ const authorComponent = addon.authorLink || addon.authorId
+ ? {getString(addon.author)}
+ : {getString(addon.author)};
const authorIndex = authorArray.findIndex(s => s == "{{author}}");
if (authorIndex) authorArray[authorIndex] = authorComponent;
return [
- React.createElement("div", {className: "bd-name"}, name),
- React.createElement("div", {className: "bd-meta"},
- React.createElement("span", {className: "bd-version"}, `v${version}`),
- ...authorArray
- )
+
- {this.props.hasSettings && this.makeControlButton(Strings.Addons.addonSettings, , this.showSettings, {disabled: !this.props.enabled})}
- {this.props.editAddon && this.makeControlButton(Strings.Addons.editAddon, , this.props.editAddon)}
- {this.props.deleteAddon && this.makeControlButton(Strings.Addons.deleteAddon, , this.props.deleteAddon, {danger: true})}
-
;
- }
-
- get footer() {
- const links = ["website", "source", "invite", "donate", "patreon"];
- const linkComponents = links.map(this.buildLink.bind(this)).filter(c => c);// linkComponents.map((comp, i) => i < linkComponents.length - 1 ? [comp, " | "] : comp).flat()
+ const footer = useMemo(() => {
+ const links = Object.keys(LinkIcons);
+ const linkComponents = links.map(l => buildLink(l, addon[l])).filter(c => c);
return
-
- {this.props.type === "plugin" ?
:
}
-
{this.buildTitle(name, version, {name: author, id: this.props.addon.authorId, link: this.props.addon.authorLink})}
-
+
+ {hasSettings && makeButton(Strings.Addons.addonSettings, , showSettings, {isControl: true, disabled: !enabled})}
+ {editAddon && makeButton(Strings.Addons.editAddon, , editAddon, {isControl: true})}
+ {deleteAddon && makeButton(Strings.Addons.deleteAddon, , deleteAddon, {isControl: true, danger: true})}
-
- {this.props.disabled &&
{`An error was encountered while trying to load this ${this.props.type}.`}
}
-
{SimpleMarkdown.parseToReact(description)}
-
- {this.footer}
;
- }
+ }, [hasSettings, editAddon, deleteAddon]);
+
+ return
+
+ {type === "plugin" ?
:
}
+
{title}
+
+
+
+ {disabled &&
{`An error was encountered while trying to load this ${type}.`}
}
+
{SimpleMarkdown.parseToReact(getString(addon.description))}
+
+ {footer}
+
;
}
-
-const originalRender = AddonCard.prototype.render;
-Object.defineProperty(AddonCard.prototype, "render", {
- enumerable: false,
- configurable: false,
- set: function() {Logger.warn("AddonCard", "Addon policy for plugins #5 https://github.com/BetterDiscord/BetterDiscord/wiki/Addon-Policies#plugins");},
- get: () => originalRender
-});
diff --git a/renderer/src/ui/settings/addonlist.jsx b/renderer/src/ui/settings/addonlist.jsx
index eba3cb02..88221727 100644
--- a/renderer/src/ui/settings/addonlist.jsx
+++ b/renderer/src/ui/settings/addonlist.jsx
@@ -13,120 +13,119 @@ import GridIcon from "../icons/grid";
import NoResults from "../blankslates/noresults";
import EmptyImage from "../blankslates/emptyimage";
-export default class AddonList extends React.Component {
+const {useState, useCallback, useEffect, useReducer, useMemo} = React;
- constructor(props) {
- super(props);
- this.state = {query: "", sort: this.getControlState("sort", "name"), ascending: this.getControlState("ascending", true), view: this.getControlState("view", "list")};
- this.sort = this.sort.bind(this);
- this.reverse = this.reverse.bind(this);
- this.search = this.search.bind(this);
- this.update = this.update.bind(this);
- this.listView = this.listView.bind(this);
- this.gridView = this.gridView.bind(this);
- this.openFolder = this.openFolder.bind(this);
- }
+const SORT_OPTIONS = [
+ {label: Strings.Addons.name, value: "name"},
+ {label: Strings.Addons.author, value: "author"},
+ {label: Strings.Addons.version, value: "version"},
+ {label: Strings.Addons.added, value: "added"},
+ {label: Strings.Addons.modified, value: "modified"},
+ {label: Strings.Addons.isEnabled, value: "isEnabled"}
+];
- componentDidMount() {
- Events.on(`${this.props.prefix}-loaded`, this.update);
- Events.on(`${this.props.prefix}-unloaded`, this.update);
- }
+const DIRECTIONS = [
+ {label: Strings.Sorting.ascending, value: true},
+ {label: Strings.Sorting.descending, value: false}
+];
- componentWillUnmount() {
- Events.off(`${this.props.prefix}-loaded`, this.update);
- Events.off(`${this.props.prefix}-unloaded`, this.update);
- }
- onControlChange(control, value) {
- const addonlistControls = DataStore.getBDData("addonlistControls") || {};
- if (!addonlistControls[this.props.type]) addonlistControls[this.props.type] = {};
- addonlistControls[this.props.type][control] = value;
- DataStore.setBDData("addonlistControls", addonlistControls);
- }
+function openFolder(folder) {
+ const shell = require("electron").shell;
+ const open = shell.openItem || shell.openPath;
+ open(folder);
+}
- getControlState(control, defaultValue) {
- const addonlistControls = DataStore.getBDData("addonlistControls") || {};
- if (!addonlistControls[this.props.type]) return defaultValue;
- if (!addonlistControls[this.props.type].hasOwnProperty(control)) return defaultValue;
- return addonlistControls[this.props.type][control];
- }
+function blankslate(type, onClick) {
+ const message = Strings.Addons.blankSlateMessage.format({link: `https://betterdiscord.app/${type}s`, type}).toString();
+ return
+
+ ;
+}
- update() {
- this.forceUpdate();
- }
+function makeControlButton(title, children, action, selected = false) {
+ return
+ {(props) => {
+ return ;
+ }}
+ ;
+}
- reload() {
- if (this.props.refreshList) this.props.refreshList();
- this.forceUpdate();
- }
+function getState(type, control, defaultValue) {
+ const addonlistControls = DataStore.getBDData("addonlistControls") || {};
+ if (!addonlistControls[type]) return defaultValue;
+ if (!addonlistControls[type].hasOwnProperty(control)) return defaultValue;
+ return addonlistControls[type][control];
+}
- listView() {this.changeView("list");}
- gridView() {this.changeView("grid");}
- changeView(view) {
- this.onControlChange("view", view);
- this.setState({view});
- }
+function saveState(type, control, value) {
+ const addonlistControls = DataStore.getBDData("addonlistControls") || {};
+ if (!addonlistControls[type]) addonlistControls[type] = {};
+ addonlistControls[type][control] = value;
+ DataStore.setBDData("addonlistControls", addonlistControls);
+}
- reverse(value) {
- this.onControlChange("ascending", value);
- this.setState({ascending: value});
- }
+function confirmDelete(addon) {
+ return new Promise(resolve => {
+ Modals.showConfirmationModal(Strings.Modals.confirmAction, Strings.Addons.confirmDelete.format({name: addon.name}), {
+ danger: true,
+ confirmText: Strings.Addons.deleteAddon,
+ onConfirm: () => {resolve(true);},
+ onCancel: () => {resolve(false);}
+ });
+ });
+}
- sort(value) {
- this.onControlChange("sort", value);
- this.setState({sort: value});
- }
- search(event) {
- this.setState({query: event.target.value.toLocaleLowerCase()});
- }
+export default function AddonList({prefix, type, title, folder, addonList, addonState, onChange, reload, editAddon, deleteAddon}) {
+ const [query, setQuery] = useState("");
+ const [sort, setSort] = useState(getState.bind(null, type, "sort", "name"));
+ const [ascending, setAscending] = useState(getState.bind(null, type, "ascending", "true"));
+ const [view, setView] = useState(getState.bind(null, type, "view", "list"));
+ const [, forceUpdate] = useReducer(x => x + 1, 0);
- openFolder() {
- const shell = require("electron").shell;
- const open = shell.openItem || shell.openPath;
- open(this.props.folder);
- }
+ useEffect(() => {
+ Events.on(`${prefix}-loaded`, forceUpdate);
+ Events.on(`${prefix}-unloaded`, forceUpdate);
+ return () => {
+ Events.off(`${prefix}-loaded`, forceUpdate);
+ Events.off(`${prefix}-unloaded`, forceUpdate);
+ };
+ }, []);
- get sortOptions() {
- return [
- {label: Strings.Addons.name, value: "name"},
- {label: Strings.Addons.author, value: "author"},
- {label: Strings.Addons.version, value: "version"},
- {label: Strings.Addons.added, value: "added"},
- {label: Strings.Addons.modified, value: "modified"},
- {label: Strings.Addons.isEnabled, value: "isEnabled"}
- ];
- }
+ const changeView = useCallback((value) => {
+ saveState(type, "view", value);
+ setView(value);
+ }, []);
- get directions() {
- return [
- {label: Strings.Sorting.ascending, value: true},
- {label: Strings.Sorting.descending, value: false}
- ];
- }
+ const listView = useCallback(() => changeView("list"), []);
+ const gridView = useCallback(() => changeView("grid"), []);
- get emptyImage() {
- const message = Strings.Addons.blankSlateMessage.format({link: `https://betterdiscord.app/${this.props.type}s`, type: this.props.type}).toString();
- return
-
- ;
- }
+ const changeDirection = useCallback((value) => {
+ saveState(type, "ascending", value);
+ setAscending(value);
+ }, []);
- makeControlButton(title, children, action, selected = false) {
- return
- {(props) => {
- return ;
- }}
- ;
- }
+ const changeSort = useCallback((value) => {
+ saveState(type, "sort", value);
+ setSort(value);
+ }, []);
- render() {
- const {title, folder, addonList, addonState, onChange, reload} = this.props;
- const button = folder ? {title: Strings.Addons.openFolder.format({type: title}), onClick: this.openFolder} : null;
- let sortedAddons = addonList.sort((a, b) => {
- const sortByEnabled = this.state.sort === "isEnabled";
- const first = sortByEnabled ? addonState[a.id] : a[this.state.sort];
- const second = sortByEnabled ? addonState[b.id] : b[this.state.sort];
+ const search = useCallback((e) => setQuery(e.target.value.toLocaleLowerCase()), []);
+ const triggerEdit = useCallback((id) => editAddon?.(id), []);
+ const triggerDelete = useCallback(async (id) => {
+ const addon = addonList.find(a => a.id == id);
+ const shouldDelete = await confirmDelete(addon);
+ if (!shouldDelete) return;
+ if (deleteAddon) deleteAddon(addon);
+ }, []);
+
+ const button = folder ? {title: Strings.Addons.openFolder.format({type: title}), onClick: openFolder} : null;
+ const renderedCards = useMemo(() => {
+ let sorted = addonList.sort((a, b) => {
+ const sortByEnabled = sort === "isEnabled";
+ const first = sortByEnabled ? addonState[a.id] : a[sort];
+ const second = sortByEnabled ? addonState[b.id] : b[sort];
const stringSort = (str1, str2) => str1.toLocaleLowerCase().localeCompare(str2.toLocaleLowerCase());
if (typeof(first) == "string") return stringSort(first, second);
if (typeof(first) == "boolean") return (first === second) ? stringSort(a.name, b.name) : first ? -1 : 1;
@@ -134,81 +133,53 @@ export default class AddonList extends React.Component {
if (second > first) return -1;
return 0;
});
- if (!this.state.ascending) sortedAddons.reverse();
- if (this.state.query) {
- sortedAddons = sortedAddons.filter(addon => {
- let matches = addon.name.toLocaleLowerCase().includes(this.state.query);
- matches = matches || addon.author.toLocaleLowerCase().includes(this.state.query);
- matches = matches || addon.description.toLocaleLowerCase().includes(this.state.query);
+
+ if (!ascending) sorted.reverse();
+
+ if (query) {
+ sorted = sorted.filter(addon => {
+ let matches = addon.name.toLocaleLowerCase().includes(query);
+ matches = matches || addon.author.toLocaleLowerCase().includes(query);
+ matches = matches || addon.description.toLocaleLowerCase().includes(query);
if (!matches) return false;
return true;
});
}
- const renderedCards = sortedAddons.map(addon => {
+ return sorted.map(addon => {
const hasSettings = addon.instance && typeof(addon.instance.getSettingsPanel) === "function";
const getSettings = hasSettings && addon.instance.getSettingsPanel.bind(addon.instance);
- return
;
+ return
triggerEdit(addon.id)} deleteAddon={() => triggerDelete(addon.id)} key={addon.id} enabled={addonState[addon.id]} addon={addon} onChange={onChange} reload={reload} hasSettings={hasSettings} getSettingsPanel={getSettings} />;
});
+ }, [addonList, addonState, sort, ascending, query]);
- const hasAddonsInstalled = this.props.addonList.length !== 0;
- const isSearching = !!this.state.query;
- const hasResults = sortedAddons.length !== 0;
+ const hasAddonsInstalled = addonList.length !== 0;
+ const isSearching = !!query;
+ const hasResults = renderedCards.length !== 0;
- return [
-
,
-
-
-
-
-
-
-
-
-
-
-
-
+ return [
+
,
+
+
+
+
+
+
+
-
- {this.makeControlButton("List View",
, this.listView, this.state.view === "list")}
- {this.makeControlButton("Grid View",
, this.gridView, this.state.view === "grid")}
+
+
+
-
,
- !hasAddonsInstalled && this.emptyImage,
- isSearching && !hasResults && hasAddonsInstalled &&
,
- hasAddonsInstalled &&
{renderedCards}
- ];
- }
-
- editAddon(id) {
- if (this.props.editAddon) this.props.editAddon(id);
- }
-
- async deleteAddon(id) {
- const addon = this.props.addonList.find(a => a.id == id);
- const shouldDelete = await this.confirmDelete(addon);
- if (!shouldDelete) return;
- if (this.props.deleteAddon) this.props.deleteAddon(addon);
- }
-
- confirmDelete(addon) {
- return new Promise(resolve => {
- Modals.showConfirmationModal(Strings.Modals.confirmAction, Strings.Addons.confirmDelete.format({name: addon.name}), {
- danger: true,
- confirmText: Strings.Addons.deleteAddon,
- onConfirm: () => {resolve(true);},
- onCancel: () => {resolve(false);}
- });
- });
- }
+
+ {makeControlButton("List View", , listView, view === "list")}
+ {makeControlButton("Grid View", , gridView, view === "grid")}
+
+
+
,
+ !hasAddonsInstalled && blankslate(type, () => openFolder(folder)),
+ isSearching && !hasResults && hasAddonsInstalled &&
,
+ hasAddonsInstalled &&
{renderedCards}
+ ];
}
-
-const originalRender = AddonList.prototype.render;
-Object.defineProperty(AddonList.prototype, "render", {
- enumerable: false,
- configurable: false,
- set: function() {Logger.warn("AddonList", "Addon policy for plugins #5 https://github.com/BetterDiscord/BetterDiscord/wiki/Addon-Policies#plugins");},
- get: () => originalRender
-});
diff --git a/renderer/src/ui/settings/drawer.jsx b/renderer/src/ui/settings/drawer.jsx
index ac2857fb..692b0114 100644
--- a/renderer/src/ui/settings/drawer.jsx
+++ b/renderer/src/ui/settings/drawer.jsx
@@ -2,52 +2,42 @@ import {React} from "modules";
import Title from "./title";
import Divider from "../divider";
+const {useState, useCallback, useRef} = React;
+
const baseClassName = "bd-settings-group";
-export default class Drawer extends React.Component {
- constructor(props) {
- super(props);
- if (this.props.button && this.props.collapsible) {
- const original = this.props.button.onClick;
- this.props.button.onClick = (event) => {
- event.stopPropagation();
- original(...arguments);
- };
- }
+export default function Drawer({name, collapsible, shown = true, showDivider, children, button, onDrawerToggle}) {
+ const container = useRef(null);
+ const [collapsed, setCollapsed] = useState(collapsible && !shown);
+ const toggleCollapse = useCallback(() => {
+ const drawer = container.current;
+ const timeout = collapsed ? 300 : 1;
+ drawer.style.setProperty("height", drawer.scrollHeight + "px");
+ drawer.classList.add("animating");
+ if (onDrawerToggle) onDrawerToggle(collapsed);
+ setCollapsed(!collapsed);
+ setTimeout(() => {
+ drawer.style.setProperty("height", "");
+ drawer.classList.remove("animating");
+ }, timeout);
+
+ }, [collapsed]);
- if (!this.props.hasOwnProperty("shown")) this.props.shown = true;
- this.container = React.createRef();
- this.state = {
- collapsed: this.props.collapsible && !this.props.shown
- };
+ const onClick = useCallback((event) => {
+ event.stopPropagation();
+ button?.onClick(...arguments);
+ }, [button]);
- this.toggleCollapse = this.toggleCollapse.bind(this);
- }
+ const collapseClass = collapsible ? `collapsible ${collapsed ? "collapsed" : "expanded"}` : "";
+ const groupClass = `${baseClassName} ${collapseClass}`;
- toggleCollapse() {
- const container = this.container.current;
- const timeout = this.state.collapsed ? 300 : 1;
- container.style.setProperty("height", container.scrollHeight + "px");
- container.classList.add("animating");
- this.setState({collapsed: !this.state.collapsed}, () => setTimeout(() => {
- container.style.setProperty("height", "");
- container.classList.remove("animating");
- }, timeout));
- if (this.props.onDrawerToggle) this.props.onDrawerToggle(this.state.collapsed);
- }
-
- render() {
- const collapseClass = this.props.collapsible ? `collapsible ${this.state.collapsed ? "collapsed" : "expanded"}` : "";
- const groupClass = `${baseClassName} ${collapseClass}`;
-
- return
-
-
- {this.props.children}
-
- {this.props.showDivider &&
}
-
;
- }
+ return
+
+
+ {children}
+
+ {showDivider &&
}
+
;
}
\ No newline at end of file
diff --git a/renderer/src/ui/settings/group.jsx b/renderer/src/ui/settings/group.jsx
index 4911135e..2c96ac7d 100644
--- a/renderer/src/ui/settings/group.jsx
+++ b/renderer/src/ui/settings/group.jsx
@@ -10,38 +10,29 @@ import Radio from "./components/radio";
import Keybind from "./components/keybind";
import Color from "./components/color";
+const {useCallback} = React;
-export default class Group extends React.Component {
- constructor(props) {
- super(props);
- this.onChange = this.onChange.bind(this);
- }
+export default function Group({onChange, id, name, button, shown, onDrawerToggle, showDivider, collapsible, settings}) {
+ const change = useCallback((settingId, value) => {
+ if (id) onChange?.(id, settingId, value);
+ else onChange?.(settingId, value);
+ }, [id]);
- onChange(id, value) {
- if (!this.props.onChange) return;
- if (this.props.id) this.props.onChange(this.props.id, id, value);
- else this.props.onChange(id, value);
- this.forceUpdate();
- }
-
- render() {
- const {settings} = this.props;
-
- return
- {settings.filter(s => !s.hidden).map((setting) => {
- let component = null;
- if (setting.type == "dropdown") component = ;
- if (setting.type == "number") component = ;
- if (setting.type == "switch") component = ;
- if (setting.type == "text") component = ;
- if (setting.type == "slider") component = ;
- if (setting.type == "radio") component = ;
- if (setting.type == "keybind") component = ;
- if (setting.type == "color") component = ;
- if (!component) return null;
- return - {component}
;
- })}
- ;
- }
+ return
+ {settings.filter(s => !s.hidden).map((setting) => {
+ let component = null;
+ const callback = value => change(setting.id, value);
+ if (setting.type == "dropdown") component = ;
+ if (setting.type == "number") component = ;
+ if (setting.type == "switch") component = ;
+ if (setting.type == "text") component = ;
+ if (setting.type == "slider") component = ;
+ if (setting.type == "radio") component = ;
+ if (setting.type == "keybind") component = ;
+ if (setting.type == "color") component = ;
+ if (!component) return null;
+ return - {component}
;
+ })}
+ ;
}
\ No newline at end of file
diff --git a/renderer/src/ui/settings/title.jsx b/renderer/src/ui/settings/title.jsx
index b318631c..8cdc9ff2 100644
--- a/renderer/src/ui/settings/title.jsx
+++ b/renderer/src/ui/settings/title.jsx
@@ -1,27 +1,25 @@
import {React} from "modules";
-const className = "bd-settings-title";
-const className2 = "bd-settings-title bd-settings-group-title";
+const {useCallback} = React;
-export default class SettingsTitle extends React.Component {
- constructor(props) {
- super(props);
- this.buttonClick = this.buttonClick.bind(this);
- }
- buttonClick(event) {
+const basicClass = "bd-settings-title";
+const groupClass = "bd-settings-title bd-settings-group-title";
+
+export default function SettingsTitle({isGroup, className, button, onClick, text, otherChildren}) {
+ const click = useCallback((event) => {
event.stopPropagation();
event.preventDefault();
- this.props?.button?.onClick?.(event);
- }
+ button?.onClick?.(event);
+ }, []);
+
+
+ const baseClass = isGroup ? groupClass : basicClass;
+ const titleClass = className ? `${baseClass} ${className}` : baseClass;
+ return
{onClick?.();}}>
+ {text}
+ {button && }
+ {otherChildren}
+
;
- render() {
- const baseClass = this.props.isGroup ? className2 : className;
- const titleClass = this.props.className ? `${baseClass} ${this.props.className}` : baseClass;
- return
{this.props.onClick && this.props.onClick();}}>
- {this.props.text}
- {this.props.button && }
- {this.props.otherChildren}
-
;
- }
}
\ No newline at end of file