Merge pull request #2686 from SillyTavern/fix-extensions-toggle Wait for settings before reloading after toggling extensions
Signed| @@ -21,6 +21,7 @@ const defaultUrl = 'http://localhost:5100'; | |||
| 21 | let saveMetadataTimeout = null; | 21 | let saveMetadataTimeout = null; |
| 22 | 22 | ||
| 23 | let requiresReload = false; | 23 | let requiresReload = false; |
| 24 | let stateChanged = false; | ||
| 24 | 25 | ||
| 25 | export function saveMetadataDebounced() { | 26 | export function saveMetadataDebounced() { |
| 26 | const context = getContext(); | 27 | const context = getContext(); |
| @@ -238,6 +239,7 @@ function onEnableExtensionClick() { | |||
| 238 | 239 | ||
| 239 | async function enableExtension(name, reload = true) { | 240 | async function enableExtension(name, reload = true) { |
| 240 | extension_settings.disabledExtensions = extension_settings.disabledExtensions.filter(x => x !== name); | 241 | extension_settings.disabledExtensions = extension_settings.disabledExtensions.filter(x => x !== name); |
| 242 | stateChanged = true; | ||
| 241 | await saveSettings(); | 243 | await saveSettings(); |
| 242 | if (reload) { | 244 | if (reload) { |
| 243 | location.reload(); | 245 | location.reload(); |
| @@ -248,6 +250,7 @@ async function enableExtension(name, reload = true) { | |||
| 248 | 250 | ||
| 249 | async function disableExtension(name, reload = true) { | 251 | async function disableExtension(name, reload = true) { |
| 250 | extension_settings.disabledExtensions.push(name); | 252 | extension_settings.disabledExtensions.push(name); |
| 253 | stateChanged = true; | ||
| 251 | await saveSettings(); | 254 | await saveSettings(); |
| 252 | if (reload) { | 255 | if (reload) { |
| 253 | location.reload(); | 256 | location.reload(); |
| @@ -657,7 +660,20 @@ async function showExtensionsDetails() { | |||
| 657 | await oldPopup.complete(POPUP_RESULT.CANCELLED); | 660 | await oldPopup.complete(POPUP_RESULT.CANCELLED); |
| 658 | } | 661 | } |
| 659 | 662 | ||
| 660 | const popup = new Popup(html, POPUP_TYPE.TEXT, '', { okButton: 'Close', wide: true, large: true, customButtons: [updateAllButton], allowVerticalScrolling: true }); | 663 | const popup = new Popup(html, POPUP_TYPE.TEXT, '', { |
| 664 | okButton: 'Close', | ||
| 665 | wide: true, | ||
| 666 | large: true, | ||
| 667 | customButtons: [updateAllButton], | ||
| 668 | allowVerticalScrolling: true, | ||
| 669 | onClosing: async () => { | ||
| 670 | if (stateChanged) { | ||
| 671 | toastr.info('The page will be reloaded shortly...', 'Extensions state changed'); | ||
| 672 | await saveSettings(); | ||
| 673 | } | ||
| 674 | return true; | ||
| 675 | }, | ||
| 676 | }); | ||
| 661 | popupPromise = popup.show(); | 677 | popupPromise = popup.show(); |
| 662 | } catch (error) { | 678 | } catch (error) { |
| 663 | toastr.error('Error loading extensions. See browser console for details.'); | 679 | toastr.error('Error loading extensions. See browser console for details.'); |
| @@ -40,8 +40,8 @@ export const POPUP_RESULT = { | |||
| 40 | * @property {POPUP_RESULT|number?} [defaultResult=POPUP_RESULT.AFFIRMATIVE] - The default result of this popup when Enter is pressed. Can be changed from `POPUP_RESULT.AFFIRMATIVE`. | 40 | * @property {POPUP_RESULT|number?} [defaultResult=POPUP_RESULT.AFFIRMATIVE] - The default result of this popup when Enter is pressed. Can be changed from `POPUP_RESULT.AFFIRMATIVE`. |
| 41 | * @property {CustomPopupButton[]|string[]?} [customButtons=null] - Custom buttons to add to the popup. If only strings are provided, the buttons will be added with default options, and their result will be in order from `2` onward. | 41 | * @property {CustomPopupButton[]|string[]?} [customButtons=null] - Custom buttons to add to the popup. If only strings are provided, the buttons will be added with default options, and their result will be in order from `2` onward. |
| 42 | * @property {CustomPopupInput[]?} [customInputs=null] - Custom inputs to add to the popup. The display below the content and the input box, one by one. | 42 | * @property {CustomPopupInput[]?} [customInputs=null] - Custom inputs to add to the popup. The display below the content and the input box, one by one. |
| 43 | * @property {(popup: Popup) => boolean?} [onClosing=null] - Handler called before the popup closes, return `false` to cancel the close | 43 | * @property {(popup: Popup) => Promise<boolean?>|boolean?} [onClosing=null] - Handler called before the popup closes, return `false` to cancel the close |
| 44 | * @property {(popup: Popup) => void?} [onClose=null] - Handler called after the popup closes, but before the DOM is cleaned up | 44 | * @property {(popup: Popup) => Promise<void?>|void?} [onClose=null] - Handler called after the popup closes, but before the DOM is cleaned up |
| 45 | * @property {number?} [cropAspect=null] - Aspect ratio for the crop popup | 45 | * @property {number?} [cropAspect=null] - Aspect ratio for the crop popup |
| 46 | * @property {string?} [cropImage=null] - Image URL to display in the crop popup | 46 | * @property {string?} [cropImage=null] - Image URL to display in the crop popup |
| 47 | */ | 47 | */ |
| @@ -138,8 +138,8 @@ export class Popup { | |||
| 138 | /** @readonly @type {CustomPopupButton[]|string[]?} */ customButtons; | 138 | /** @readonly @type {CustomPopupButton[]|string[]?} */ customButtons; |
| 139 | /** @readonly @type {CustomPopupInput[]} */ customInputs; | 139 | /** @readonly @type {CustomPopupInput[]} */ customInputs; |
| 140 | 140 | ||
| 141 | /** @type {(popup: Popup) => boolean?} */ onClosing; | 141 | /** @type {(popup: Popup) => Promise<boolean?>|boolean?} */ onClosing; |
| 142 | /** @type {(popup: Popup) => void?} */ onClose; | 142 | /** @type {(popup: Popup) => Promise<void?>|void?} */ onClose; |
| 143 | 143 | ||
| 144 | /** @type {POPUP_RESULT|number} */ result; | 144 | /** @type {POPUP_RESULT|number} */ result; |
| 145 | /** @type {any} */ value; | 145 | /** @type {any} */ value; |
| @@ -509,7 +509,7 @@ export class Popup { | |||
| 509 | this.result = result; | 509 | this.result = result; |
| 510 | 510 | ||
| 511 | if (this.onClosing) { | 511 | if (this.onClosing) { |
| 512 | const shouldClose = this.onClosing(this); | 512 | const shouldClose = await this.onClosing(this); |
| 513 | if (!shouldClose) { | 513 | if (!shouldClose) { |
| 514 | this.#isClosingPrevented = true; | 514 | this.#isClosingPrevented = true; |
| 515 | // Set values back if we cancel out of closing the popup | 515 | // Set values back if we cancel out of closing the popup |
| @@ -547,13 +547,13 @@ export class Popup { | |||
| 547 | fixToastrForDialogs(); | 547 | fixToastrForDialogs(); |
| 548 | 548 | ||
| 549 | // After the dialog is actually completely closed, remove it from the DOM | 549 | // After the dialog is actually completely closed, remove it from the DOM |
| 550 | runAfterAnimation(this.dlg, () => { | 550 | runAfterAnimation(this.dlg, async () => { |
| 551 | // Call the close on the dialog | 551 | // Call the close on the dialog |
| 552 | this.dlg.close(); | 552 | this.dlg.close(); |
| 553 | 553 | ||
| 554 | // Run a possible custom handler right before DOM removal | 554 | // Run a possible custom handler right before DOM removal |
| 555 | if (this.onClose) { | 555 | if (this.onClose) { |
| 556 | this.onClose(this); | 556 | await this.onClose(this); |
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | // Remove it from the dom | 559 | // Remove it from the dom |