Skip to content

Commit 2f74bee

Browse files
MarkShawn2020claude
andcommitted
feat(chat): 为 MessageView 添加面包屑导航
- 在 chat-messages view 类型中添加 projectPath 字段 - 更新所有导航调用传递 projectPath - 将 "← Sessions" 按钮替换为 "项目名 / Session名" 面包屑 - 项目名可点击返回 Sessions 列表 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 62faf01 commit 2f74bee

4 files changed

Lines changed: 33 additions & 22 deletions

File tree

src/App.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ function App() {
251251
<Home
252252
onFeatureClick={handleFeatureClick}
253253
onProjectClick={(p) => navigate({ type: "chat-sessions", projectId: p.id, projectPath: p.path })}
254-
onSessionClick={(s) => navigate({ type: "chat-messages", projectId: s.project_id, sessionId: s.id, summary: s.summary })}
254+
onSessionClick={(s) => navigate({ type: "chat-messages", projectId: s.project_id, projectPath: s.project_path || '', sessionId: s.id, summary: s.summary })}
255255
onSearch={() => navigate({ type: "chat-projects" })}
256256
onOpenAnnualReport={() => navigate({ type: "annual-report-2025" })}
257257
/>
@@ -264,24 +264,25 @@ function App() {
264264
{view.type === "chat-projects" && (
265265
<ProjectList
266266
onSelectProject={(p) => navigate({ type: "chat-sessions", projectId: p.id, projectPath: p.path })}
267-
onSelectSession={(s) => navigate({ type: "chat-messages", projectId: s.project_id, sessionId: s.id, summary: s.summary })}
268-
onSelectChat={(c) => navigate({ type: "chat-messages", projectId: c.project_id, sessionId: c.session_id, summary: c.session_summary })}
267+
onSelectSession={(s) => navigate({ type: "chat-messages", projectId: s.project_id, projectPath: s.project_path || '', sessionId: s.id, summary: s.summary })}
268+
onSelectChat={(c) => navigate({ type: "chat-messages", projectId: c.project_id, projectPath: c.project_path, sessionId: c.session_id, summary: c.session_summary })}
269269
/>
270270
)}
271271
{view.type === "chat-sessions" && (
272272
<SessionList
273273
projectId={view.projectId}
274274
projectPath={view.projectPath}
275275
onBack={() => navigate({ type: "chat-projects" })}
276-
onSelect={(s) => navigate({ type: "chat-messages", projectId: s.project_id, sessionId: s.id, summary: s.summary })}
276+
onSelect={(s) => navigate({ type: "chat-messages", projectId: s.project_id, projectPath: s.project_path || '', sessionId: s.id, summary: s.summary })}
277277
/>
278278
)}
279279
{view.type === "chat-messages" && (
280280
<MessageView
281281
projectId={view.projectId}
282+
projectPath={view.projectPath}
282283
sessionId={view.sessionId}
283284
summary={view.summary}
284-
onBack={() => navigate({ type: "chat-sessions", projectId: view.projectId, projectPath: "" })}
285+
onBack={() => navigate({ type: "chat-sessions", projectId: view.projectId, projectPath: view.projectPath })}
285286
/>
286287
)}
287288
{(view.type === "commands" || view.type === "command-detail" || view.type === "mcp" ||
@@ -382,7 +383,7 @@ function App() {
382383
<DistillDetailView
383384
document={view.document}
384385
onBack={() => navigate({ type: "kb-distill" })}
385-
onNavigateSession={(projectId, sessionId, summary) => navigate({ type: "chat-messages", projectId, sessionId, summary })}
386+
onNavigateSession={(projectId, projectPath, sessionId, summary) => navigate({ type: "chat-messages", projectId, projectPath, sessionId, summary })}
386387
/>
387388
)}
388389
{(view.type === "kb-reference" || view.type === "kb-reference-doc") && (
@@ -579,7 +580,7 @@ function App() {
579580
<Home
580581
onFeatureClick={handleFeatureClick}
581582
onProjectClick={(p) => navigate({ type: "chat-sessions", projectId: p.id, projectPath: p.path })}
582-
onSessionClick={(s) => navigate({ type: "chat-messages", projectId: s.project_id, sessionId: s.id, summary: s.summary })}
583+
onSessionClick={(s) => navigate({ type: "chat-messages", projectId: s.project_id, projectPath: s.project_path || '', sessionId: s.id, summary: s.summary })}
583584
onSearch={() => navigate({ type: "chat-projects" })}
584585
onOpenAnnualReport={() => navigate({ type: "annual-report-2025" })}
585586
/>
@@ -593,8 +594,8 @@ function App() {
593594
{view.type === "chat-projects" && (
594595
<ProjectList
595596
onSelectProject={(p) => navigate({ type: "chat-sessions", projectId: p.id, projectPath: p.path })}
596-
onSelectSession={(s) => navigate({ type: "chat-messages", projectId: s.project_id, sessionId: s.id, summary: s.summary })}
597-
onSelectChat={(c) => navigate({ type: "chat-messages", projectId: c.project_id, sessionId: c.session_id, summary: c.session_summary })}
597+
onSelectSession={(s) => navigate({ type: "chat-messages", projectId: s.project_id, projectPath: s.project_path || '', sessionId: s.id, summary: s.summary })}
598+
onSelectChat={(c) => navigate({ type: "chat-messages", projectId: c.project_id, projectPath: c.project_path, sessionId: c.session_id, summary: c.session_summary })}
598599
/>
599600
)}
600601

@@ -603,16 +604,17 @@ function App() {
603604
projectId={view.projectId}
604605
projectPath={view.projectPath}
605606
onBack={() => navigate({ type: "chat-projects" })}
606-
onSelect={(s) => navigate({ type: "chat-messages", projectId: s.project_id, sessionId: s.id, summary: s.summary })}
607+
onSelect={(s) => navigate({ type: "chat-messages", projectId: s.project_id, projectPath: s.project_path || '', sessionId: s.id, summary: s.summary })}
607608
/>
608609
)}
609610

610611
{view.type === "chat-messages" && (
611612
<MessageView
612613
projectId={view.projectId}
614+
projectPath={view.projectPath}
613615
sessionId={view.sessionId}
614616
summary={view.summary}
615-
onBack={() => navigate({ type: "chat-sessions", projectId: view.projectId, projectPath: "" })}
617+
onBack={() => navigate({ type: "chat-sessions", projectId: view.projectId, projectPath: view.projectPath })}
616618
/>
617619
)}
618620

@@ -715,7 +717,7 @@ function App() {
715717
<DistillDetailView
716718
document={view.document}
717719
onBack={() => navigate({ type: "kb-distill" })}
718-
onNavigateSession={(projectId, sessionId, summary) => navigate({ type: "chat-messages", projectId, sessionId, summary })}
720+
onNavigateSession={(projectId, projectPath, sessionId, summary) => navigate({ type: "chat-messages", projectId, projectPath, sessionId, summary })}
719721
/>
720722
)}
721723
{(view.type === "kb-reference" || view.type === "kb-reference-doc") && (

src/types/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export type View =
202202
| { type: "features" }
203203
| { type: "chat-projects" }
204204
| { type: "chat-sessions"; projectId: string; projectPath: string }
205-
| { type: "chat-messages"; projectId: string; sessionId: string; summary: string | null }
205+
| { type: "chat-messages"; projectId: string; projectPath: string; sessionId: string; summary: string | null }
206206
| { type: "settings" }
207207
| { type: "commands" }
208208
| { type: "command-detail"; command: LocalCommand; scrollToChangelog?: boolean }

src/views/Chat/MessageView.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ import { originalChatAtom, markdownPreviewAtom } from "../../store";
2323
import { CollapsibleContent } from "./CollapsibleContent";
2424
import { ExportDialog } from "./ExportDialog";
2525
import { restoreSlashCommand } from "./utils";
26+
import { useAppConfig } from "../../context";
2627
import type { Message } from "../../types";
2728

2829
interface MessageViewProps {
2930
projectId: string;
31+
projectPath: string;
3032
sessionId: string;
3133
summary: string | null;
3234
onBack: () => void;
3335
}
3436

35-
export function MessageView({ projectId, sessionId, summary, onBack }: MessageViewProps) {
37+
export function MessageView({ projectId, projectPath, sessionId, summary, onBack }: MessageViewProps) {
38+
const { formatPath } = useAppConfig();
3639
const [messages, setMessages] = useState<Message[]>([]);
3740
const [loading, setLoading] = useState(true);
3841
const [originalChat, setOriginalChat] = useAtom(originalChatAtom);
@@ -86,12 +89,18 @@ export function MessageView({ projectId, sessionId, summary, onBack }: MessageVi
8689
return (
8790
<div className="px-6 py-8">
8891
<header className="mb-8">
89-
<button
90-
onClick={onBack}
91-
className="text-muted-foreground-foreground hover:text-foreground flex items-center gap-1 text-sm mb-4"
92-
>
93-
<span></span> Sessions
94-
</button>
92+
<nav className="flex items-center gap-1.5 text-sm mb-4">
93+
<button
94+
onClick={onBack}
95+
className="text-muted-foreground hover:text-foreground transition-colors truncate max-w-[200px]"
96+
>
97+
{projectPath ? formatPath(projectPath) : projectId}
98+
</button>
99+
<span className="text-muted-foreground/50">/</span>
100+
<span className="text-foreground truncate max-w-[300px]">
101+
{summary || "Session"}
102+
</span>
103+
</nav>
95104
<div className="flex items-start justify-between gap-4">
96105
<ContextMenu>
97106
<ContextMenuTrigger asChild>

src/views/Knowledge/DistillDetailView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
interface DistillDetailViewProps {
1414
document: DistillDocument;
1515
onBack: () => void;
16-
onNavigateSession: (projectId: string, sessionId: string, summary: string | null) => void;
16+
onNavigateSession: (projectId: string, projectPath: string, sessionId: string, summary: string | null) => void;
1717
}
1818

1919
export function DistillDetailView({
@@ -38,7 +38,7 @@ export function DistillDetailView({
3838
sessionId: document.session,
3939
});
4040
if (session) {
41-
onNavigateSession(session.project_id, session.id, session.summary);
41+
onNavigateSession(session.project_id, session.project_path || '', session.id, session.summary);
4242
}
4343
};
4444

0 commit comments

Comments
 (0)