feat(settings): reset plugins & settings options(#57)

* start of channelbadges

* update badges

* give in and add colors to settings page, refactor

* change from styles.css to style.css

* update for linter

* forgot to remove dm css no need for them

* Fixes

* update PluginModal.tsx and src/components/PluginSettings/index.tsx

adds options to disable all plugins and a option to reset a plugins settings to the default state

* Update warning image and image size in PluginModal and PluginSettings

---------

Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
Creation's 2024-10-15 10:17:43 -04:00 committed by GitHub
parent 2cb70a7cb8
commit 70c15730b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 226 additions and 14 deletions

View file

@ -30,7 +30,7 @@ import { classes, isObjectEmpty } from "@utils/misc";
import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
import { OptionType, Plugin } from "@utils/types"; import { OptionType, Plugin } from "@utils/types";
import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; import { findByPropsLazy, findComponentByCodeLazy } from "@webpack";
import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common"; import { Button, Clickable, FluxDispatcher, Forms, React, Text, Toasts, Tooltip, UserStore, UserUtils } from "@webpack/common";
import { User } from "discord-types/general"; import { User } from "discord-types/general";
import { Constructor } from "type-fest"; import { Constructor } from "type-fest";
@ -139,6 +139,10 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
onClose(); onClose();
} }
function handleResetClick() {
openWarningModal(plugin, { onClose, transitionState }, onRestartNeeded);
}
function renderSettings() { function renderSettings() {
if (!hasSettings || !plugin.options) { if (!hasSettings || !plugin.options) {
return <Forms.FormText>There are no settings for this plugin.</Forms.FormText>; return <Forms.FormText>There are no settings for this plugin.</Forms.FormText>;
@ -279,29 +283,45 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
</ModalContent> </ModalContent>
{hasSettings && <ModalFooter> {hasSettings && <ModalFooter>
<Flex flexDirection="column" style={{ width: "100%" }}> <Flex flexDirection="column" style={{ width: "100%" }}>
<Flex style={{ marginLeft: "auto" }}> <Flex style={{ justifyContent: "space-between" }}>
<Button <Tooltip text="Reset to default settings" shouldShow={!isObjectEmpty(tempSettings)}>
onClick={onClose}
size={Button.Sizes.SMALL}
color={Button.Colors.PRIMARY}
look={Button.Looks.LINK}
>
Cancel
</Button>
<Tooltip text="You must fix all errors before saving" shouldShow={!canSubmit()}>
{({ onMouseEnter, onMouseLeave }) => ( {({ onMouseEnter, onMouseLeave }) => (
<Button <Button
size={Button.Sizes.SMALL} size={Button.Sizes.SMALL}
color={Button.Colors.BRAND} color={Button.Colors.BRAND}
onClick={saveAndClose} onClick={handleResetClick}
onMouseEnter={onMouseEnter} onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}
disabled={!canSubmit()} style={{ backgroundColor: "var(--button-danger-background)" }}
> >
Save & Close Reset
</Button> </Button>
)} )}
</Tooltip> </Tooltip>
<Flex style={{ marginLeft: "auto" }}>
<Button
onClick={onClose}
size={Button.Sizes.SMALL}
color={Button.Colors.PRIMARY}
look={Button.Looks.LINK}
>
Cancel
</Button>
<Tooltip text="You must fix all errors before saving" shouldShow={!canSubmit()}>
{({ onMouseEnter, onMouseLeave }) => (
<Button
size={Button.Sizes.SMALL}
color={Button.Colors.BRAND}
onClick={saveAndClose}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
disabled={!canSubmit()}
>
Save & Close
</Button>
)}
</Tooltip>
</Flex>
</Flex> </Flex>
{saveError && <Text variant="text-md/semibold" style={{ color: "var(--text-danger)" }}>Error while saving: {saveError}</Text>} {saveError && <Text variant="text-md/semibold" style={{ color: "var(--text-danger)" }}>Error while saving: {saveError}</Text>}
</Flex> </Flex>
@ -319,3 +339,125 @@ export function openPluginModal(plugin: Plugin, onRestartNeeded?: (pluginName: s
/> />
)); ));
} }
function resetSettings(plugin: Plugin, warningModalProps?: ModalProps, pluginModalProps?: ModalProps, onRestartNeeded?: (pluginName: string) => void) {
const defaultSettings = plugin.settings?.def;
const pluginName = plugin.name;
if (!defaultSettings) {
console.error(`No default settings found for ${pluginName}`);
return;
}
const newSettings: Record<string, any> = {};
let restartNeeded = false;
for (const key in defaultSettings) {
if (key === "enabled") continue;
const setting = defaultSettings[key];
setting.type = setting.type ?? OptionType.STRING;
if (setting.type === OptionType.STRING) {
newSettings[key] = setting.default !== undefined && setting.default !== "" ? setting.default : "";
} else if ("default" in setting && setting.default !== undefined) {
newSettings[key] = setting.default;
}
if (setting?.restartNeeded) {
restartNeeded = true;
}
}
const currentSettings = plugin.settings?.store;
if (currentSettings) {
Object.assign(currentSettings, newSettings);
}
if (plugin.afterSave) {
plugin.afterSave();
}
if (restartNeeded) {
onRestartNeeded?.(plugin.name);
}
Toasts.show({
message: `Settings for ${pluginName} have been reset.`,
id: Toasts.genId(),
type: Toasts.Type.SUCCESS,
options: {
position: Toasts.Position.TOP
}
});
warningModalProps?.onClose();
pluginModalProps?.onClose();
}
export function openWarningModal(plugin: Plugin, pluginModalProps: ModalProps, onRestartNeeded?: (pluginName: string) => void) {
openModal(warningModalProps => (
<ModalRoot
{...warningModalProps}
size={ModalSize.SMALL}
className="vc-text-selectable"
transitionState={warningModalProps.transitionState}
>
<ModalHeader separator={false}>
<Text style={{ flexGrow: 1, color: "var(--text-danger)", fontSize: "1.4rem", fontWeight: "bold" }}>Warning: Dangerous Action</Text>
<ModalCloseButton onClick={warningModalProps.onClose} />
</ModalHeader>
<ModalContent>
<Forms.FormSection>
<Flex className="vc-warning-info" style={{ gap: "15px", flexDirection: "column", userSelect: "none" }}>
<img
src="https://media.tenor.com/Y6DXKZiBCs8AAAAi/stavario-josefbenes.gif"
alt="Warning"
style={{ width: "60%", height: "auto", marginBottom: "10px", display: "block", margin: "auto" }}
/>
<Text style={{ fontSize: "1.2rem", color: "var(--text-normal)" }}>
You are about to reset all settings for <strong>{plugin.name}</strong> to their default values.
</Text>
<Text style={{ fontSize: "1.2rem", color: "var(--text-danger)", fontWeight: "bold" }}>
This action is irreversible.
</Text>
<Text style={{ fontSize: "1.2rem", color: "var(--text-normal)", marginBottom: "10px" }}>
If you are certain you want to proceed, click <strong>Confirm Reset</strong>. Otherwise, click <strong>Cancel</strong>.
</Text>
</Flex>
</Forms.FormSection>
</ModalContent>
<ModalFooter>
<Flex flexDirection="column" style={{ width: "100%" }}>
<Flex style={{ justifyContent: "space-between" }}>
<Button
size={Button.Sizes.SMALL}
color={Button.Colors.PRIMARY}
onClick={warningModalProps.onClose}
look={Button.Looks.LINK}
>
Cancel
</Button>
<Tooltip text="This action cannot be undone. Are you sure?" shouldShow={true}>
{({ onMouseEnter, onMouseLeave }) => (
<Button
size={Button.Sizes.SMALL}
color={Button.Colors.BRAND}
onClick={() => {
resetSettings(plugin, warningModalProps, pluginModalProps, onRestartNeeded);
}}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
style={{ marginLeft: "10px", backgroundColor: "var(--button-danger-background)" }}
>
Confirm Reset
</Button>
)}
</Tooltip>
</Flex>
</Flex>
</ModalFooter>
</ModalRoot>
));
}

View file

@ -386,6 +386,76 @@ export default function PluginSettings() {
</div> </div>
<Forms.FormTitle className={Margins.top20}>Plugins</Forms.FormTitle> <Forms.FormTitle className={Margins.top20}>Plugins</Forms.FormTitle>
{enabledPlugins.length > 0 && (
<Button
size={Button.Sizes.SMALL}
style={{ backgroundColor: "var(--button-danger-background)", margin: "20px 0" }}
onClick={() => {
return Alerts.show({
title: "Disable All Plugins",
body: (
<>
<img
src="https://media.tenor.com/Y6DXKZiBCs8AAAAi/stavario-josefbenes.gif"
alt="Warning"
style={{ width: "60%", height: "auto", marginBottom: "10px", display: "block", margin: "auto" }}
/>
<p style={{ fontSize: "1.2rem", color: "var(--text-danger)", fontWeight: "bold" }}>
WARNING: You are about to disable <span style={{ textDecoration: "underline" }}>{enabledPlugins.length}</span> plugins!
</p>
<p style={{ fontSize: "1rem" }}>
Are you absolutely sure you want to proceed? You can always enable them back later.
</p>
</>
),
confirmText: "Disable All",
cancelText: "Cancel",
onConfirm: () => {
let restartNeeded = false;
for (const plugin of enabledPlugins) {
const pluginSettings = settings.plugins[plugin];
if (Plugins[plugin].patches?.length) {
pluginSettings.enabled = false;
changes.handleChange(plugin);
restartNeeded = true;
continue;
}
const result = stopPlugin(Plugins[plugin]);
if (!result) {
logger.error(`Error while stopping plugin ${plugin}`);
showErrorToast(`Error while stopping plugin ${plugin}`);
continue;
}
pluginSettings.enabled = false;
}
if (restartNeeded) {
Alerts.show({
title: "Restart Required",
body: (
<>
<p>Some plugins require a restart to fully disable.</p>
<p>Would you like to restart now?</p>
</>
),
confirmText: "Restart Now",
cancelText: "Later",
onConfirm: () => location.reload()
});
}
}
});
}}
>
Disable All Plugins
</Button>
)}
{plugins.length || requiredPlugins.length {plugins.length || requiredPlugins.length
? ( ? (