diff --git a/apps/web/src/components/BranchToolbar.tsx b/apps/web/src/components/BranchToolbar.tsx index f13490a3f702d6abd2a897d37a7c8ad535980bfe..21113658fcd3d99320b2a19cdbd1f5fa2873f5a8 100644 --- a/apps/web/src/components/BranchToolbar.tsx +++ b/apps/web/src/components/BranchToolbar.tsx @@ -23,6 +23,7 @@ import { import { ChevronDownIcon } from "lucide-react"; interface BranchToolbarProps { + threadId: string; envMode: "local" | "worktree"; onEnvModeChange: (mode: "local" | "worktree") => void; envLocked: boolean; @@ -30,6 +31,7 @@ interface BranchToolbarProps { } export default function BranchToolbar({ + threadId, envMode, onEnvModeChange, envLocked, @@ -42,7 +44,7 @@ export default function BranchToolbar({ const [isBranchMenuOpen, setIsBranchMenuOpen] = useState(false); const [branchQuery, setBranchQuery] = useState(""); - const activeThread = state.threads.find((thread) => thread.id === state.activeThreadId); + const activeThread = state.threads.find((thread) => thread.id === threadId); const activeProject = state.projects.find((project) => project.id === activeThread?.projectId); const activeThreadId = activeThread?.id; const activeThreadBranch = activeThread?.branch ?? null; diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index b51308274ff6ba8db11c79fa593284e52e96e35f..7169e1796bbfefb79447c42ba51ee9c5f77bf992 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -63,6 +63,7 @@ import { } from "../session-logic"; import { isScrollContainerNearBottom } from "../chat-scroll"; import { useStore } from "../store"; +import { truncateTitle } from "../truncateTitle"; import { DEFAULT_THREAD_TERMINAL_ID, MAX_THREAD_TERMINAL_COUNT, @@ -1129,6 +1130,9 @@ export default function ChatView({ threadId }: ChatViewProps) { revokePreviewUrls(existing); return []; }); + setPrompt(""); + promptRef.current = ""; + setIsSending(false); setComposerCursor(0); setComposerHighlightedItemId(null); dragDepthRef.current = 0; @@ -1650,7 +1654,7 @@ export default function ChatView({ threadId }: ChatViewProps) { (composerImagesSnapshot.length > 0 ? `Image: ${composerImagesSnapshot[0]?.name ?? "attachment"}` : "New thread"); - const title = titleSeed.length > 50 ? `${titleSeed.slice(0, 50)}...` : titleSeed; + const title = truncateTitle(titleSeed); dispatch({ type: "SET_THREAD_TITLE", threadId: activeThread.id, @@ -1944,6 +1948,7 @@ export default function ChatView({ threadId }: ChatViewProps) { className={`flex items-center justify-between border-b border-border px-5 ${isElectron ? "drag-region h-[52px]" : "py-3"}`} > )} - {activeProjectName && } - {activeProjectName && } + {activeProjectName && ( + + )} + {activeProjectName && ( + + )} (() => { const stored = localStorage.getItem(LAST_EDITOR_KEY); @@ -2855,7 +2869,7 @@ const OpenInPicker = memo(function OpenInPicker({ const api = useNativeApi(); const { state } = useStore(); - const activeThread = state.threads.find((t) => t.id === state.activeThreadId); + const activeThread = state.threads.find((t) => t.id === activeThreadId); const activeProject = state.projects.find((p) => p.id === activeThread?.projectId); const openInEditor = useCallback( diff --git a/apps/web/src/components/GitActionsControl.tsx b/apps/web/src/components/GitActionsControl.tsx index 7890665a9d3ba767c352394da443812640f9edad..11b5fc45236b60a006f86dcfe08243b5d36eec34 100644 --- a/apps/web/src/components/GitActionsControl.tsx +++ b/apps/web/src/components/GitActionsControl.tsx @@ -38,12 +38,12 @@ import { gitStatusQueryOptions, invalidateGitQueries, } from "~/lib/gitReactQuery"; -import { useStore } from "~/store"; import { preferredTerminalEditor, resolvePathLinkTarget } from "~/terminal-links"; interface GitActionsControlProps { api: NativeApi | undefined; gitCwd: string | null; + activeThreadId: string | null; } function getMenuActionDisabledReason( @@ -136,9 +136,11 @@ function GitQuickActionIcon({ quickAction }: { quickAction: GitQuickAction }) { return ; } -export default function GitActionsControl({ api, gitCwd }: GitActionsControlProps) { - const { state } = useStore(); - const activeThreadId = state.activeThreadId; +export default function GitActionsControl({ + api, + gitCwd, + activeThreadId, +}: GitActionsControlProps) { const threadToastData = useMemo( () => (activeThreadId ? { threadId: activeThreadId } : undefined), [activeThreadId], diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index 35ae22e1af0a066d393f712f87e810ac995d85ba..9f9b5f15bd57043c9dc459d866e306af493884a6 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -397,7 +397,9 @@ export default function Sidebar() { useEffect(() => { const onWindowKeyDown = (event: KeyboardEvent) => { - const activeThread = state.threads.find((t) => t.id === state.activeThreadId); + const activeThread = routeThreadId + ? state.threads.find((thread) => thread.id === routeThreadId) + : undefined; if (isChatNewLocalShortcut(event, keybindings)) { const projectId = activeThread?.projectId ?? state.projects[0]?.id; if (!projectId) return; @@ -420,7 +422,7 @@ export default function Sidebar() { return () => { window.removeEventListener("keydown", onWindowKeyDown); }; - }, [handleNewThread, keybindings, state.activeThreadId, state.projects, state.threads]); + }, [handleNewThread, keybindings, routeThreadId, state.projects, state.threads]); return (