Fix make `/profile` await the for an actual successful API connection (#4589) * fix: add connection status check after profile switch in connection manager Fixes #4262 * feat: add timeout parameter to connection manager await functionality & catch timout error * Add rejectOnTimeout option to waitUntilCondition --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import { DOMPurify, Fuse } from '../../../lib.js'; |
| 2 | 2 | |
| 3 | 3 | import { event_types, eventSource, main_api, online_status, saveSettingsDebounced } from '../../../script.js'; |
| 4 | 4 | import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js'; |
| 5 | 5 | import { callGenericPopup, Popup, POPUP_RESULT, POPUP_TYPE } from '../../popup.js'; |
| 6 | 6 | import { SlashCommand } from '../../slash-commands/SlashCommand.js'; |
| @@ -11,7 +11,7 @@ import { SlashCommandDebugController } from '../../slash-commands/SlashCommandDe | ||
| 11 | 11 | import { enumTypes, SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js'; |
| 12 | 12 | import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; |
| 13 | 13 | import { SlashCommandScope } from '../../slash-commands/SlashCommandScope.js'; |
| 14 | 14 | import { collapseSpaces, getUniqueName, isFalseBoolean, uuidv4, waitUntilCondition } from '../../utils.js'; |
| 15 | 15 | import { t } from '../../i18n.js'; |
| 16 | 16 | import { getSecretLabelById } from '../../secrets.js'; |
| 17 | 17 | |
| @@ -684,6 +684,13 @@ async function renderDetailsContent(detailsContent) { | ||
| 684 | 684 | defaultValue: 'true', |
| 685 | 685 | enumList: commonEnumProviders.boolean('trueFalse')(), |
| 686 | 686 | }), |
| 687 | + SlashCommandNamedArgument.fromProps({ | |
| 688 | + name: 'timeout', | |
| 689 | + description: 'Maximum time to wait for the API connection to be established, in milliseconds. Set to 0 to disable. Only applies when await=true.', | |
| 690 | + isRequired: false, | |
| 691 | + typeList: [ARGUMENT_TYPE.NUMBER], | |
| 692 | + defaultValue: '2000', | |
| 693 | + }), | |
| 687 | 694 | ], |
| 688 | 695 | callback: async (args, value) => { |
| 689 | 696 | if (!value || typeof value !== 'string') { |
| @@ -715,6 +722,13 @@ async function renderDetailsContent(detailsContent) { | ||
| 715 | 722 | |
| 716 | 723 | if (shouldAwait) { |
| 717 | 724 | await awaitPromise; |
| 725 | + | |
| 726 | + // We should also await the connection to be established | |
| 727 | + const parsedTimeout = parseInt(args?.timeout?.toString()); | |
| 728 | + const timeout = !isNaN(parsedTimeout) ? Math.max(0, parsedTimeout) : 2000; | |
| 729 | + if (timeout > 0) { | |
| 730 | + await waitUntilCondition(() => online_status !== 'no_connection', timeout, 100, { rejectOnTimeout: false }); | |
| 731 | + } | |
| 718 | 732 | } |
| 719 | 733 | |
| 720 | 734 | return profile.name; |
| @@ -1637,13 +1637,18 @@ export function createThumbnail(dataUrl, maxWidth = null, maxHeight = null, type | ||
| 1637 | 1637 | * @param {{ (): boolean; }} condition The condition to wait for. |
| 1638 | 1638 | * @param {number} [timeout=1000] The timeout in milliseconds. |
| 1639 | 1639 | * @param {number} [interval=100] The interval in milliseconds. |
| 1640 | + * @param {object} [options] Options object | |
| 1641 | + * @param {boolean} [options.rejectOnTimeout=true] Whether to reject the promise on timeout or resolve it. | |
| 1640 | 1642 | * @returns {Promise<void>} A promise that resolves when the condition is true. |
| 1641 | 1643 | */ |
| 1642 | 1644 | export async function waitUntilCondition(condition, timeout = 1000, interval = 100, options = {}) { |
| 1645 | + const { rejectOnTimeout = true } = options; | |
| 1646 | + | |
| 1643 | 1647 | return new Promise((resolve, reject) => { |
| 1644 | 1648 | const timeoutId = setTimeout(() => { |
| 1645 | 1649 | clearInterval(intervalId); |
| 1646 | - reject(new Error('Timed out waiting for condition to be true')); | |
| 1650 | + const timeoutFn = rejectOnTimeout ? reject : resolve; | |
| 1651 | + timeoutFn(new Error('Timed out waiting for condition to be true')); | |
| 1647 | 1652 | }, timeout); |
| 1648 | 1653 | |
| 1649 | 1654 | const intervalId = setInterval(() => { |