diff --git a/apps/mobile/src/state/use-selected-thread-git-actions.test.ts b/apps/mobile/src/state/use-selected-thread-git-actions.test.ts index 5867021e347e1d44e0dd9a4966680a1c6a72f618..6da5672851a0cc123af2c36604e599d766df3190 100644 --- a/apps/mobile/src/state/use-selected-thread-git-actions.test.ts +++ b/apps/mobile/src/state/use-selected-thread-git-actions.test.ts @@ -26,6 +26,7 @@ vi.mock("react", () => ({ useCallback: (callback: unknown) => callback, useMemo: (factory: () => unknown) => factory(), useEffect: () => {}, + useEffectEvent: (callback: unknown) => callback, })); vi.mock("./session", () => ({ useEnvironmentScope: (environmentId: unknown, scope: string) => diff --git a/apps/mobile/src/state/use-selected-thread-git-actions.ts b/apps/mobile/src/state/use-selected-thread-git-actions.ts index be19904ff95e2025aa3a18804b0888b7f056b48b..54e8bcd439ea4b8337551a29023270d52057ec8f 100644 --- a/apps/mobile/src/state/use-selected-thread-git-actions.ts +++ b/apps/mobile/src/state/use-selected-thread-git-actions.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect, useEffectEvent, useMemo } from "react"; import { EnvironmentProject, EnvironmentThreadShell } from "@t3tools/client-runtime/state/shell"; import type { AtomCommandResult } from "@t3tools/client-runtime/state/runtime"; @@ -140,12 +140,26 @@ export function useSelectedThreadGitActions() { [refreshStatus, selectedThread, selectedThreadCwd, selectedThreadProject], ); + // Shell updates replace the selected thread object many times per second while a + // turn streams, so key the refresh on primitives. The server publishes status after + // each turn finishes; this only seeds status when the selection or cwd changes. + const selectedEnvironmentId = selectedThread?.environmentId ?? null; + const selectedThreadId = selectedThread?.id ?? null; + const hasSelectedThreadProject = selectedThreadProject !== null; + const refreshOnSelection = useEffectEvent(() => { + void refreshSelectedThreadGitStatus({ quiet: true }); + }); useEffect(() => { - if (!selectedThread || !selectedThreadProject) { + if ( + selectedEnvironmentId === null || + selectedThreadId === null || + !hasSelectedThreadProject || + selectedThreadCwd === null + ) { return; } - void refreshSelectedThreadGitStatus({ quiet: true }); - }, [refreshSelectedThreadGitStatus, selectedThread, selectedThreadProject]); + refreshOnSelection(); + }, [selectedEnvironmentId, selectedThreadId, hasSelectedThreadProject, selectedThreadCwd]); const runSelectedThreadGitMutation = useCallback( async (