From 52c91aa5b0f9efd7bc8cafcf76d64a8ad4045aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=85=E8=A5=BF?= Date: Thu, 28 May 2026 15:42:59 +0800 Subject: [PATCH] fix(desktop): debounce workflow deeplink generation --- .../src/components/recipes/CreateEditRecipeModal.tsx | 10 ++++++++-- ui/desktop/src/recipe/index.ts | 9 ++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ui/desktop/src/components/recipes/CreateEditRecipeModal.tsx b/ui/desktop/src/components/recipes/CreateEditRecipeModal.tsx index 3b3b1eabade2..f47bcd07c9c5 100644 --- a/ui/desktop/src/components/recipes/CreateEditRecipeModal.tsx +++ b/ui/desktop/src/components/recipes/CreateEditRecipeModal.tsx @@ -339,6 +339,7 @@ export default function CreateEditRecipeModal({ // Generate deeplink whenever recipe configuration changes useEffect(() => { let isCancelled = false; + const abortController = new AbortController(); const generateLink = async () => { if ( @@ -353,11 +354,14 @@ export default function CreateEditRecipeModal({ setIsGeneratingDeeplink(true); try { const currentRecipe = getCurrentRecipe(); - const link = await generateDeepLink(currentRecipe); + const link = await generateDeepLink(currentRecipe, abortController.signal); if (!isCancelled) { setDeeplink(link); } } catch (error) { + if (abortController.signal.aborted) { + return; + } console.error('Failed to generate deeplink:', error); if (!isCancelled) { setDeeplink('Error generating deeplink'); @@ -369,10 +373,12 @@ export default function CreateEditRecipeModal({ } }; - generateLink(); + const timeoutId = window.setTimeout(generateLink, 500); return () => { isCancelled = true; + abortController.abort(); + window.clearTimeout(timeoutId); }; }, [ title, diff --git a/ui/desktop/src/recipe/index.ts b/ui/desktop/src/recipe/index.ts index 4d52ad140f72..ba2ff2c49c5a 100644 --- a/ui/desktop/src/recipe/index.ts +++ b/ui/desktop/src/recipe/index.ts @@ -15,10 +15,13 @@ export type Recipe = import('../api').Recipe & { isScheduledExecution?: boolean; }; -export async function encodeRecipe(recipe: Recipe): Promise { +type ApiSignal = Parameters[0]['signal']; + +export async function encodeRecipe(recipe: Recipe, signal?: ApiSignal): Promise { try { const response = await apiEncodeRecipe({ body: { recipe }, + signal, }); if (!response.data) { @@ -71,8 +74,8 @@ export async function scanRecipe(recipe: Recipe): Promise<{ has_security_warning } } -export async function generateDeepLink(recipe: Recipe): Promise { - const encoded = await encodeRecipe(recipe); +export async function generateDeepLink(recipe: Recipe, signal?: ApiSignal): Promise { + const encoded = await encodeRecipe(recipe, signal); return `goose://recipe?config=${encoded}`; }