From 41ce282e955c66b71317ffa597308008aaa084e9 Mon Sep 17 00:00:00 2001 From: Ryanba <92616678+Gujiassh@users.noreply.github.com> Date: Thu, 12 Mar 2026 12:12:31 +0800 Subject: [PATCH] fix(stage-ui): skip optimistic updates before apply (#1304) * fix(stage-ui): skip optimistic updates before apply Avoid leaving phantom optimistic state behind when a mutation is intentionally skipped by checking the guard before applying the optimistic update. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus * [autofix.ci] apply automated fixes --------- Co-authored-by: Sisyphus Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../locales/vi/tamagotchi/electron/tray.yaml | 2 +- .../src/composables/use-optimistic.test.ts | 27 +++++++++++++++++++ .../src/composables/use-optimistic.ts | 3 ++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/i18n/src/locales/vi/tamagotchi/electron/tray.yaml b/packages/i18n/src/locales/vi/tamagotchi/electron/tray.yaml index 4f8662e64..e26fe8b54 100644 --- a/packages/i18n/src/locales/vi/tamagotchi/electron/tray.yaml +++ b/packages/i18n/src/locales/vi/tamagotchi/electron/tray.yaml @@ -20,7 +20,7 @@ menu: open_caption: Mở phụ đề... caption_overlay: Lớp phủ phụ đề follow_window: Theo cửa sổ - reset_position: Đặt lại vị trí + reset_position: Đặt lại vị trí devtools: Công cụ phát triển troubleshoot_beatsync: Sửa lỗi BeatSync... quit: Thoát ra diff --git a/packages/stage-ui/src/composables/use-optimistic.test.ts b/packages/stage-ui/src/composables/use-optimistic.test.ts index e89c325e6..ad36fd64a 100644 --- a/packages/stage-ui/src/composables/use-optimistic.test.ts +++ b/packages/stage-ui/src/composables/use-optimistic.test.ts @@ -120,4 +120,31 @@ describe('useOptimistic', () => { await execute() expect(error.value).toBeDefined() }) + + it('should skip without applying optimistic state', async () => { + const state = ref('initial') + const apply = vi.fn(() => { + state.value = 'optimistic' + return () => { + state.value = 'initial' + } + }) + const action = vi.fn(async () => 'should-not-run') + const skipActionIf = vi.fn(() => true) + + const { execute, state: resultState } = useOptimisticMutation({ + apply, + action, + skipActionIf, + lazy: true, + }) + + await execute() + + expect(skipActionIf).toHaveBeenCalled() + expect(apply).not.toHaveBeenCalled() + expect(action).not.toHaveBeenCalled() + expect(state.value).toBe('initial') + expect(resultState.value).toBeUndefined() + }) }) diff --git a/packages/stage-ui/src/composables/use-optimistic.ts b/packages/stage-ui/src/composables/use-optimistic.ts index 644bb98d4..decedb258 100644 --- a/packages/stage-ui/src/composables/use-optimistic.ts +++ b/packages/stage-ui/src/composables/use-optimistic.ts @@ -50,11 +50,12 @@ export function useOptimisticMutation(options: UseOptimis } = options return useAsyncState(async () => { - const rollback = await apply() if (skipActionIf && await skipActionIf()) { return undefined as R } + const rollback = await apply() + try { const result = await action() if (onSuccess) {