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 (