From 42d76abbba5109017b049f97571982f100a6c06a Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:41:54 +0200 Subject: [PATCH] TeactN: Support Promise from actions (#5972) --- src/global/index.ts | 1 + src/lib/teact/teactn.tsx | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/global/index.ts b/src/global/index.ts index 7c12cd7b5..f63052d28 100644 --- a/src/global/index.ts +++ b/src/global/index.ts @@ -47,6 +47,7 @@ type ActionHandlers = { export const getGlobal = typed.getGlobal; export const setGlobal = typed.setGlobal; export const getActions = typed.getActions; +export const getPromiseActions = typed.getPromiseActions; export const addActionHandler = typed.addActionHandler as ( name: ActionName, handler: ActionHandlers[ActionName], diff --git a/src/lib/teact/teactn.tsx b/src/lib/teact/teactn.tsx index d2e1ef020..a40d004db 100644 --- a/src/lib/teact/teactn.tsx +++ b/src/lib/teact/teactn.tsx @@ -2,6 +2,7 @@ import type { FC, FC_withDebug, Props } from './teact'; import { DEBUG, DEBUG_MORE } from '../../config'; import arePropsShallowEqual, { logUnequalProps } from '../../util/arePropsShallowEqual'; +import Deferred from '../../util/Deferred'; import { handleError } from '../../util/handleError'; import { orderBy } from '../../util/iteratees'; import { throttleWithTickEnd } from '../../util/schedulers'; @@ -132,15 +133,25 @@ export function forceOnHeavyAnimationOnce() { let actionQueue: NoneToVoidFunction[] = []; -function handleAction(name: string, payload?: ActionPayload, options?: ActionOptions) { +function handleAction(name: string, payload?: ActionPayload, options?: ActionOptions): Promise { + const deferred = new Deferred(); actionQueue.push(() => { actionHandlers[name]?.forEach((handler) => { const response = handler(DEBUG ? getUntypedGlobal() : currentGlobal, actions, payload); - if (!response || typeof response.then === 'function') { + if (!response) { + deferred.resolve(); + return; + } + + if (typeof response.then === 'function') { + response.then(() => { + deferred.resolve(); + }); return; } setUntypedGlobal(response as GlobalState, options); + deferred.resolve(); }); }); @@ -154,6 +165,8 @@ function handleAction(name: string, payload?: ActionPayload, options?: ActionOpt actionQueue = []; } } + + return deferred.promise; } function updateContainers() { @@ -221,7 +234,7 @@ export function addUntypedActionHandler(name: ActionNames, handler: ActionHandle actionHandlers[name] = []; actions[name] = (payload?: ActionPayload, options?: ActionOptions) => { - handleAction(name, payload, options); + return handleAction(name, payload, options); }; } @@ -312,12 +325,12 @@ export function typify< type ProjectActionNames = keyof ActionPayloads; // When payload is allowed to be `undefined` we consider it optional - type ProjectActions = { + type ProjectActions = { [ActionName in ProjectActionNames]: (undefined extends ActionPayloads[ActionName] ? ( - (payload?: ActionPayloads[ActionName], options?: ActionOptions) => void + (payload?: ActionPayloads[ActionName], options?: ActionOptions) => ReturnType ) : ( - (payload: ActionPayloads[ActionName], options?: ActionOptions) => void + (payload: ActionPayloads[ActionName], options?: ActionOptions) => ReturnType )) }; @@ -333,6 +346,7 @@ export function typify< getGlobal: getUntypedGlobal as () => T, setGlobal: setUntypedGlobal as (state: ProjectGlobalState, options?: ActionOptions) => void, getActions: getUntypedActions as () => ProjectActions, + getPromiseActions: getUntypedActions as () => ProjectActions>, addActionHandler: addUntypedActionHandler as ( name: ActionName, handler: ActionHandlers[ActionName],