Skip to content

Commit ac16da0

Browse files
MarkShawn2020claude
andcommitted
refactor(ui): 重构 MessageView header 控件布局
- 合并 Raw + Clean 为单一 Original 开关,还原对话现场 - 将控件分为 View 和 Filter 两组,每组独占一行 - 用 pill 按钮替代 Switch 组件,更优雅简洁 - 修复 ExportDialog 预览区域溢出问题 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 6451261 commit ac16da0

1 file changed

Lines changed: 86 additions & 66 deletions

File tree

src/App.tsx

Lines changed: 86 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,7 +2135,7 @@ function ExportDialog({ open, onOpenChange, messages, processContent, defaultNam
21352135

21362136
return (
21372137
<Dialog open={open} onOpenChange={onOpenChange}>
2138-
<DialogContent className="max-w-2xl max-h-[80vh] flex flex-col">
2138+
<DialogContent className="!flex !flex-col max-w-2xl max-h-[80vh] overflow-hidden">
21392139
<DialogHeader>
21402140
<DialogTitle>Export {messages.length} Messages</DialogTitle>
21412141
</DialogHeader>
@@ -2191,10 +2191,10 @@ function ExportDialog({ open, onOpenChange, messages, processContent, defaultNam
21912191
)}
21922192
</div>
21932193

2194-
<div className="flex-1 overflow-auto min-h-0 mt-4">
2195-
<div className="text-xs text-muted mb-2">Preview</div>
2196-
<div className="bg-card-alt rounded-lg p-4 text-sm text-ink overflow-auto font-mono whitespace-pre-wrap">
2197-
{preview.slice(0, 5000)}{preview.length > 5000 && '...'}
2194+
<div className="flex-1 flex flex-col min-h-[200px] overflow-hidden mt-4">
2195+
<div className="text-xs text-muted mb-2 shrink-0">Preview</div>
2196+
<div className="flex-1 bg-card-alt rounded-lg p-4 text-sm text-ink overflow-auto font-mono whitespace-pre-wrap break-all">
2197+
{preview}
21982198
</div>
21992199
</div>
22002200

@@ -2227,9 +2227,8 @@ function MessageView({
22272227
}) {
22282228
const [messages, setMessages] = useState<Message[]>([]);
22292229
const [loading, setLoading] = useState(true);
2230-
const [rawCommands, setRawCommands] = usePersistedState("lovcode:rawCommands", true);
2230+
const [originalChat, setOriginalChat] = usePersistedState("lovcode:originalChat", true);
22312231
const [markdownPreview, setMarkdownPreview] = usePersistedState("lovcode:markdownPreview", false);
2232-
const [hideIntermediate, setHideIntermediate] = usePersistedState("lovcode:hideIntermediate", false);
22332232
const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
22342233
const [selectMode, setSelectMode] = usePersistedState("lovcode:selectMode", false);
22352234
const [selectPreset, setSelectPreset] = usePersistedState<"all" | "user" | "none">("lovcode:selectPreset", "all");
@@ -2241,10 +2240,10 @@ function MessageView({
22412240
}, [projectId, sessionId]);
22422241

22432242
const processContent = (content: string) => {
2244-
return rawCommands ? restoreSlashCommand(content) : content;
2243+
return originalChat ? restoreSlashCommand(content) : content;
22452244
};
22462245

2247-
const filteredMessages = hideIntermediate
2246+
const filteredMessages = originalChat
22482247
? messages.filter(m => !m.is_meta && !m.is_tool)
22492248
: messages;
22502249

@@ -2296,77 +2295,98 @@ function MessageView({
22962295
);
22972296
}
22982297

2298+
const pillBase = "px-2.5 py-1 text-xs rounded-full transition-colors";
2299+
const pillActive = "bg-primary/15 text-primary";
2300+
const pillInactive = "text-muted hover:text-ink hover:bg-card-alt";
2301+
const groupLabel = "text-[10px] uppercase tracking-wider text-muted px-2";
2302+
22992303
return (
23002304
<div className="px-6 py-8">
2301-
<header className="mb-6">
2302-
<div className="flex items-center justify-between mb-2">
2303-
<button
2304-
onClick={onBack}
2305-
className="text-muted hover:text-ink flex items-center gap-1 text-sm"
2306-
>
2307-
<span></span> Sessions
2308-
</button>
2309-
<div className="flex items-center gap-4">
2310-
<label className="flex items-center gap-2 text-sm text-muted cursor-pointer">
2311-
<Switch checked={selectMode} onCheckedChange={(v) => { setSelectMode(v); if (!v) deselectAll(); }} />
2312-
<span>Select</span>
2313-
</label>
2314-
<label className="flex items-center gap-2 text-sm text-muted cursor-pointer">
2315-
<Switch checked={rawCommands} onCheckedChange={setRawCommands} />
2316-
<span>Raw input</span>
2317-
</label>
2318-
<label className="flex items-center gap-2 text-sm text-muted cursor-pointer">
2319-
<Switch checked={hideIntermediate} onCheckedChange={setHideIntermediate} />
2320-
<span>Clean</span>
2321-
</label>
2322-
<label className="flex items-center gap-2 text-sm text-muted cursor-pointer">
2323-
<Switch checked={markdownPreview} onCheckedChange={setMarkdownPreview} />
2324-
<span>Preview</span>
2325-
</label>
2326-
</div>
2327-
</div>
2328-
<div className="flex items-center gap-2">
2329-
<h1 className="font-serif text-xl font-semibold text-ink line-clamp-2">
2305+
<header className="mb-8">
2306+
<button
2307+
onClick={onBack}
2308+
className="text-muted hover:text-ink flex items-center gap-1 text-sm mb-4"
2309+
>
2310+
<span></span> Sessions
2311+
</button>
2312+
<div className="flex items-start justify-between gap-4 mb-6">
2313+
<h1 className="font-serif text-2xl font-semibold text-ink leading-tight">
23302314
{summary || "Session"}
23312315
</h1>
23322316
<button
23332317
onClick={() => invoke("reveal_session_file", { projectId, sessionId })}
2334-
className="text-muted hover:text-ink transition-colors"
2318+
className="text-muted hover:text-ink transition-colors shrink-0 mt-1"
23352319
title="Reveal in Finder"
23362320
>
2337-
<FolderOpen size={16} />
2321+
<FolderOpen size={18} />
23382322
</button>
23392323
</div>
2340-
{selectMode && (
2341-
<div className="flex items-center gap-2 mt-3">
2342-
<button
2343-
onClick={selectAll}
2344-
className={`text-xs px-2 py-1 rounded transition-colors ${selectPreset === "all" ? "bg-primary text-primary-foreground" : "bg-card-alt hover:bg-border text-muted hover:text-ink"}`}
2345-
>
2346-
All
2347-
</button>
2348-
<button
2349-
onClick={selectUserOnly}
2350-
className={`text-xs px-2 py-1 rounded transition-colors ${selectPreset === "user" ? "bg-primary text-primary-foreground" : "bg-card-alt hover:bg-border text-muted hover:text-ink"}`}
2351-
>
2352-
User
2353-
</button>
2354-
<button
2355-
onClick={deselectAll}
2356-
className={`text-xs px-2 py-1 rounded transition-colors ${selectPreset === "none" ? "bg-primary text-primary-foreground" : "bg-card-alt hover:bg-border text-muted hover:text-ink"}`}
2357-
>
2358-
None
2359-
</button>
2360-
{selectedIds.size > 0 && (
2324+
<div className="space-y-2">
2325+
<div className="flex items-center gap-3">
2326+
<span className={groupLabel}>View</span>
2327+
<div className="flex items-center gap-1">
23612328
<button
2362-
onClick={() => setExportDialogOpen(true)}
2363-
className="text-xs px-2 py-1 rounded bg-primary text-primary-foreground hover:bg-primary/90 transition-colors"
2329+
onClick={() => setOriginalChat(!originalChat)}
2330+
className={`${pillBase} ${originalChat ? pillActive : pillInactive}`}
2331+
title="Show original conversation (restore slash commands, hide tool calls)"
23642332
>
2365-
Export {exportCount}
2333+
Original
23662334
</button>
2367-
)}
2335+
<button
2336+
onClick={() => setMarkdownPreview(!markdownPreview)}
2337+
className={`${pillBase} ${markdownPreview ? pillActive : pillInactive}`}
2338+
title="Render markdown"
2339+
>
2340+
Markdown Preview
2341+
</button>
2342+
</div>
23682343
</div>
2369-
)}
2344+
<div className="flex items-center gap-3">
2345+
<span className={groupLabel}>Filter</span>
2346+
<div className="flex items-center gap-1">
2347+
<button
2348+
onClick={() => { setSelectMode(!selectMode); if (selectMode) deselectAll(); }}
2349+
className={`${pillBase} ${selectMode ? pillActive : pillInactive}`}
2350+
>
2351+
Select
2352+
</button>
2353+
{selectMode && (
2354+
<>
2355+
<span className="w-px h-3 bg-border mx-1" />
2356+
<button
2357+
onClick={selectAll}
2358+
className={`${pillBase} ${selectPreset === "all" ? pillActive : pillInactive}`}
2359+
>
2360+
All
2361+
</button>
2362+
<button
2363+
onClick={selectUserOnly}
2364+
className={`${pillBase} ${selectPreset === "user" ? pillActive : pillInactive}`}
2365+
>
2366+
User
2367+
</button>
2368+
<button
2369+
onClick={deselectAll}
2370+
className={`${pillBase} ${selectPreset === "none" ? pillActive : pillInactive}`}
2371+
>
2372+
None
2373+
</button>
2374+
{selectedIds.size > 0 && (
2375+
<>
2376+
<span className="w-px h-3 bg-border mx-1" />
2377+
<button
2378+
onClick={() => setExportDialogOpen(true)}
2379+
className="px-3 py-1 text-xs rounded-full bg-primary text-primary-foreground hover:bg-primary/90 transition-colors"
2380+
>
2381+
Export {exportCount}
2382+
</button>
2383+
</>
2384+
)}
2385+
</>
2386+
)}
2387+
</div>
2388+
</div>
2389+
</div>
23702390
</header>
23712391

23722392
<div className="space-y-4">

0 commit comments

Comments
 (0)