Add /extension-toggle

a6445aee1b1399d0f0de27b0d0cff1037e236cdb

Wolfsblvt <wolfsblvt@gmail.com>

1 files changed, +86 -11Showing whitespace changes
public/scripts/extensions.js+86 -11
@@ -8,7 +8,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom
88import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';
99import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
1010import { renderTemplate, renderTemplateAsync } from './templates.js';
1111import { equalsIgnoreCaseAndAccents, isFalseBoolean, isSubsetOf, isTrueBoolean, setValueByPath } from './utils.js';
1212export {
1313 getContext,
1414 getApiUrl,
@@ -1050,33 +1050,50 @@ export async function openThirdPartyExtensionMenu(suggestUrl = '') {
10501050}
10511051
10521052/**
10531053 * @param {boolean'enable' | 'disable' | 'toggle'} enableaction - WhetherThe toaction enableto orperform disableon the extension
10541054 * @returns {(args: {[key: string]: string | SlashCommandClosure}, extensionName: string | SlashCommandClosure) => Promise<string>}
10551055 */
10561056function getExtensionToggleCallbackgetExtensionActionCallback(enableaction) {
10571057 return async (args, extensionName) => {
10581058 if (args?.reload instanceof SlashCommandClosure) throw new Error('\'reload\' argument cannot be a closure.');
10591059 if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.');
10601060 if (!extensionName) {
10611061 toastr.warning(`Extension name must be provided as an argument to ${enable ? 'enable' : 'disable'action} this extension.`);
10621062 return '';
10631063 }
10641064
10651065 const reload = isTrueBoolean(args?.reload);
1066-
10671066 const internalExtensionName = extensionNames.find(x => equalsIgnoreCaseAndAccents(x, extensionName));
10681067 if (!internalExtensionName) {
10691068 toastr.warning(`Extension ${extensionName} does not exist.`);
10701069 return '';
10711070 }
1072- if (enable === !extension_settings.disabledExtensions.includes(internalExtensionName)) {
1071+
1073- toastr.info(`Extension ${extensionName} is already ${enable ? 'enabled' : 'disabled'}.`);
1072+ const isEnabled = !extension_settings.disabledExtensions.includes(internalExtensionName);
1073+
1074+ if (action === 'enable' && isEnabled) {
1075+ toastr.info(`Extension ${extensionName} is already enabled.`);
10741076 return internalExtensionName;
10751077 }
10761078
1077- reload && toastr.info(`${enable ? 'Enabling' : 'Disabling'} extension ${extensionName} and reloading...`);
1079+ if (action === 'disable' && !isEnabled) {
1080+ toastr.info(`Extension ${extensionName} is already disabled.`);
1081+ return internalExtensionName;
1082+ }
1083+
1084+ if (action === 'toggle') {
1085+ action = isEnabled ? 'disable' : 'enable';
1086+ }
1087+
1088+ reload && toastr.info(`${action.charAt(0).toUpperCase() + action.slice(1)}ing extension ${extensionName} and reloading...`);
1089+
1090+ if (action === 'enable') {
10781091 await enableExtension(internalExtensionName, reload);
1079- toastr.success(`Extension ${extensionName} ${enable ? 'enabled' : 'disabled'}.`);
1092+ } else {
1093+ await disableExtension(internalExtensionName, reload);
1094+ }
1095+
1096+ toastr.success(`Extension ${extensionName} ${action}d.`);
10801097
10811098 return internalExtensionName;
10821099 };
@@ -1085,7 +1102,7 @@ function getExtensionToggleCallback(enable) {
10851102function registerExtensionSlashCommands() {
10861103 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
10871104 name: 'extension-enable',
10881105 callback: getExtensionToggleCallbackgetExtensionActionCallback(true'enable'),
10891106 namedArgumentList: [
10901107 SlashCommandNamedArgument.fromProps({
10911108 name: 'reload',
@@ -1125,7 +1142,7 @@ function registerExtensionSlashCommands() {
11251142 }));
11261143 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
11271144 name: 'extension-disable',
11281145 callback: getExtensionToggleCallbackgetExtensionActionCallback(false'enable'),
11291146 namedArgumentList: [
11301147 SlashCommandNamedArgument.fromProps({
11311148 name: 'reload',
@@ -1163,6 +1180,64 @@ function registerExtensionSlashCommands() {
11631180 </div>
11641181 `,
11651182 }));
1183+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
1184+ name: 'extension-toggle',
1185+ callback: async (args, extensionName) => {
1186+ if (args?.state instanceof SlashCommandClosure) throw new Error('\'state\' argument cannot be a closure.');
1187+ if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.');
1188+
1189+ const action = isTrueBoolean(args?.state) ? 'enable' :
1190+ isFalseBoolean(args?.state) ? 'disable' :
1191+ 'toggle';
1192+
1193+ return await getExtensionActionCallback(action)(args, extensionName);
1194+ },
1195+ namedArgumentList: [
1196+ SlashCommandNamedArgument.fromProps({
1197+ name: 'reload',
1198+ description: 'Whether to reload the page after toggling the extension',
1199+ typeList: [ARGUMENT_TYPE.BOOLEAN],
1200+ defaultValue: 'true',
1201+ enumList: commonEnumProviders.boolean('trueFalse')(),
1202+ }),
1203+ SlashCommandNamedArgument.fromProps({
1204+ name: 'state',
1205+ description: 'Explicitly set the state of the extension (true to enable, false to disable). If not provided, the state will be toggled to the opposite of the current state.',
1206+ typeList: [ARGUMENT_TYPE.BOOLEAN],
1207+ enumList: commonEnumProviders.boolean('trueFalse')(),
1208+ }),
1209+ ],
1210+ unnamedArgumentList: [
1211+ SlashCommandArgument.fromProps({
1212+ description: 'Extension name',
1213+ typeList: [ARGUMENT_TYPE.STRING],
1214+ isRequired: true,
1215+ enumProvider: () => extensionNames.map(name => new SlashCommandEnumValue(name)),
1216+ forceEnum: true,
1217+ }),
1218+ ],
1219+ helpString: `
1220+ <div>
1221+ Toggles the state of a specified extension.
1222+ </div>
1223+ <div>
1224+ By default, the page will be reloaded automatically, stopping any further commands.<br />
1225+ If <code>reload=false</code> named argument is passed, the page will not be reloaded, and the extension will stay in its current state until refreshed.
1226+ The page either needs to be refreshed, or <code>/reload-page</code> has to be called.
1227+ </div>
1228+ <div>
1229+ <strong>Example:</strong>
1230+ <ul>
1231+ <li>
1232+ <pre><code class="language-stscript">/extension-toggle Summarize</code></pre>
1233+ </li>
1234+ <li>
1235+ <pre><code class="language-stscript">/extension-toggle Summarize state=true</code></pre>
1236+ </li>
1237+ </ul>
1238+ </div>
1239+ `,
1240+ }));
11661241
11671242 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
11681243 name: 'reload-page',