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
8import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';8import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';
9import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';9import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
10import { renderTemplate, renderTemplateAsync } from './templates.js';10import { renderTemplate, renderTemplateAsync } from './templates.js';
11import { equalsIgnoreCaseAndAccents, isSubsetOf, isTrueBoolean, setValueByPath } from './utils.js';11import { equalsIgnoreCaseAndAccents, isFalseBoolean, isSubsetOf, isTrueBoolean, setValueByPath } from './utils.js';
12export {12export {
13 getContext,13 getContext,
14 getApiUrl,14 getApiUrl,
@@ -1050,33 +1050,50 @@ export async function openThirdPartyExtensionMenu(suggestUrl = '') {
1050}1050}
10511051
1052/**1052/**
1053 * @param {boolean} enable - Whether to enable or disable the extension1053 * @param {'enable' | 'disable' | 'toggle'} action - The action to perform on the extension
1054 * @returns {(args: {[key: string]: string | SlashCommandClosure}, extensionName: string | SlashCommandClosure) => Promise<string>}1054 * @returns {(args: {[key: string]: string | SlashCommandClosure}, extensionName: string | SlashCommandClosure) => Promise<string>}
1055 */1055 */
1056function getExtensionToggleCallback(enable) {1056function getExtensionActionCallback(action) {
1057 return async (args, extensionName) => {1057 return async (args, extensionName) => {
1058 if (args?.reload instanceof SlashCommandClosure) throw new Error('\'reload\' argument cannot be a closure.');1058 if (args?.reload instanceof SlashCommandClosure) throw new Error('\'reload\' argument cannot be a closure.');
1059 if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.');1059 if (typeof extensionName !== 'string') throw new Error('Extension name does only support string. Closures or arrays are not allowed.');
1060 if (!extensionName) {1060 if (!extensionName) {
1061 toastr.warning(`Extension name must be provided as an argument to ${enable ? 'enable' : 'disable'} this extension.`);1061 toastr.warning(`Extension name must be provided as an argument to ${action} this extension.`);
1062 return '';1062 return '';
1063 }1063 }
10641064
1065 const reload = isTrueBoolean(args?.reload);1065 const reload = isTrueBoolean(args?.reload);
1066
1067 const internalExtensionName = extensionNames.find(x => equalsIgnoreCaseAndAccents(x, extensionName));1066 const internalExtensionName = extensionNames.find(x => equalsIgnoreCaseAndAccents(x, extensionName));
1068 if (!internalExtensionName) {1067 if (!internalExtensionName) {
1069 toastr.warning(`Extension ${extensionName} does not exist.`);1068 toastr.warning(`Extension ${extensionName} does not exist.`);
1070 return '';1069 return '';
1071 }1070 }
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.`);
1074 return internalExtensionName;1076 return internalExtensionName;
1075 }1077 }
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') {
1078 await enableExtension(internalExtensionName, reload);1091 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
1081 return internalExtensionName;1098 return internalExtensionName;
1082 };1099 };
@@ -1085,7 +1102,7 @@ function getExtensionToggleCallback(enable) {
1085function registerExtensionSlashCommands() {1102function registerExtensionSlashCommands() {
1086 SlashCommandParser.addCommandObject(SlashCommand.fromProps({1103 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
1087 name: 'extension-enable',1104 name: 'extension-enable',
1088 callback: getExtensionToggleCallback(true),1105 callback: getExtensionActionCallback('enable'),
1089 namedArgumentList: [1106 namedArgumentList: [
1090 SlashCommandNamedArgument.fromProps({1107 SlashCommandNamedArgument.fromProps({
1091 name: 'reload',1108 name: 'reload',
@@ -1125,7 +1142,7 @@ function registerExtensionSlashCommands() {
1125 }));1142 }));
1126 SlashCommandParser.addCommandObject(SlashCommand.fromProps({1143 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
1127 name: 'extension-disable',1144 name: 'extension-disable',
1128 callback: getExtensionToggleCallback(false),1145 callback: getExtensionActionCallback('enable'),
1129 namedArgumentList: [1146 namedArgumentList: [
1130 SlashCommandNamedArgument.fromProps({1147 SlashCommandNamedArgument.fromProps({
1131 name: 'reload',1148 name: 'reload',
@@ -1163,6 +1180,64 @@ function registerExtensionSlashCommands() {
1163 </div>1180 </div>
1164 `,1181 `,
1165 }));1182 }));
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
1167 SlashCommandParser.addCommandObject(SlashCommand.fromProps({1242 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
1168 name: 'reload-page',1243 name: 'reload-page',