diff --git a/src/components/frame/Extensions/pages/ExtensionDetailsPage/partials/ExtensionSettings/utils.tsx b/src/components/frame/Extensions/pages/ExtensionDetailsPage/partials/ExtensionSettings/utils.tsx index 5f68f17d88..a6a3b088a1 100644 --- a/src/components/frame/Extensions/pages/ExtensionDetailsPage/partials/ExtensionSettings/utils.tsx +++ b/src/components/frame/Extensions/pages/ExtensionDetailsPage/partials/ExtensionSettings/utils.tsx @@ -4,7 +4,10 @@ import { type UseFormReset, type FieldValues } from 'react-hook-form'; import { toast } from 'react-toastify'; import { ExtensionDetailsPageTabId } from '~frame/Extensions/pages/ExtensionDetailsPage/types.ts'; -import { waitForDbAfterExtensionAction } from '~frame/Extensions/pages/ExtensionDetailsPage/utils.tsx'; +import { + waitForDbAfterExtensionAction, + waitForDbAfterExtensionSettingsChange, +} from '~frame/Extensions/pages/ExtensionDetailsPage/utils.tsx'; import { ExtensionMethods, type RefetchExtensionDataFn, @@ -206,6 +209,13 @@ export const handleWaitingForDbAfterFormCompletion = async ({ } } + if (isSaveChanges && extensionData.configurable) { + await waitForDbAfterExtensionSettingsChange({ + extensionData, + refetchExtensionData, + }); + } + if (method === ExtensionMethods.ENABLE) { toast.success( { + await waitForCondition( + async () => { + const previousExtensionParams = isInstalledExtensionData(extensionData) + ? extensionData.params || null + : null; + + const refetchedExtensionData = await refetchExtensionData(); + + const haveParamsUpdated = + previousExtensionParams !== refetchedExtensionData?.params; + + return haveParamsUpdated; + }, + { + interval, + timeout, + }, + ); +}; -export const waitForDbAfterExtensionAction = ( +export const waitForDbAfterExtensionAction = async ( args: { refetchExtensionData: RefetchExtensionDataFn; interval?: number; + timeout?: number; } & ( | { method: ExtensionMethods.UPGRADE; @@ -33,22 +66,15 @@ export const waitForDbAfterExtensionAction = ( } ), ) => { - const { refetchExtensionData, interval = 1000, method } = args; - - return new Promise((res, rej) => { - const initTime = new Date().valueOf(); - const intervalId = setInterval(async () => { - const thirtySeconds = 1000 * 30; - if (new Date().valueOf() - initTime > thirtySeconds) { - // after 30 seconds, assume something went wrong - clearInterval(intervalId); - rej( - new Error( - `After ${thirtySeconds} seconds, could not find extension in the database.`, - ), - ); - } - + const { + refetchExtensionData, + interval = 1000, + timeout = 30000, + method, + } = args; + + await waitForCondition( + async () => { const shouldRefetchPermissions = method === ExtensionMethods.INSTALL || method === ExtensionMethods.ENABLE; @@ -132,12 +158,13 @@ export const waitForDbAfterExtensionAction = ( } } - if (condition) { - clearInterval(intervalId); - res(); - } - }, interval); - }); + return condition; + }, + { + interval, + timeout, + }, + ); }; export const getTextChunks = () => { diff --git a/src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/ReleasePaymentModal/utils.ts b/src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/ReleasePaymentModal/utils.ts index 52f92413ae..749cdb6fad 100644 --- a/src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/ReleasePaymentModal/utils.ts +++ b/src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/ReleasePaymentModal/utils.ts @@ -1,30 +1,20 @@ import { type ExpenditurePayoutWithSlotId } from '~types/expenditures.ts'; +import { waitForCondition } from '~utils/waitForCondition.ts'; import { type RefetchExpenditureType } from '~v5/common/CompletedAction/partials/PaymentBuilder/types.ts'; -export const waitForDbAfterClaimingPayouts = ( +export const waitForDbAfterClaimingPayouts = async ( payouts: ExpenditurePayoutWithSlotId[], refetchExpenditure: RefetchExpenditureType, ) => { const interval = 1000; const timeout = 30 * 1000; // 30 seconds - return new Promise((resolve, reject) => { - const initTime = new Date().valueOf(); - const intervalId = setInterval(async () => { - if (new Date().valueOf() - initTime > timeout) { - // after timeout, assume something went wrong - clearInterval(intervalId); - reject( - new Error( - `After 30 seconds, could not verify all payouts as claimed in the database.`, - ), - ); - } - + await waitForCondition( + async () => { const response = await refetchExpenditure(); const expenditure = response.data.getExpenditure; if (!expenditure) { - return; + return false; } // Check if all payouts are claimed @@ -42,10 +32,11 @@ export const waitForDbAfterClaimingPayouts = ( return targetPayout?.isClaimed === true; }); - if (allPayoutsClaimed) { - clearInterval(intervalId); - resolve(); - } - }, interval); - }); + return allPayoutsClaimed; + }, + { + interval, + timeout, + }, + ); }; diff --git a/src/utils/waitForCondition.ts b/src/utils/waitForCondition.ts new file mode 100644 index 0000000000..3e31408cf2 --- /dev/null +++ b/src/utils/waitForCondition.ts @@ -0,0 +1,37 @@ +type CheckConditionFunction = () => Promise; + +export function waitForCondition( + checkCondition: CheckConditionFunction, + options: { + interval?: number; + timeout?: number; + customError?: string; + }, +): Promise { + const { + interval = 1000, + timeout = 30000, + customError = `After ${timeout / 1000} seconds, failed to meet condition`, + } = options; + + return new Promise((resolve, reject) => { + const initTime = new Date().valueOf(); + const intervalId = setInterval(async () => { + // Check if the timeout has been reached + if (new Date().valueOf() - initTime > timeout) { + // After timeout, assume something went wrong + clearInterval(intervalId); + reject(new Error(customError)); + return; + } + + // Check the condition + const conditionMet = await checkCondition(); + + if (conditionMet) { + clearInterval(intervalId); + resolve(); + } + }, interval); + }); +}