mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-25 13:45:03 +08:00
perf: collapse long session messages to reduce text layout cost
Messages over 3000 characters are now truncated to 1500 characters by default, with an expand/collapse toggle. This avoids expensive browser text layout for large AI responses containing code or tool output.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { memo } from "react";
|
||||
import { Copy } from "lucide-react";
|
||||
import { memo, useState } from "react";
|
||||
import { ChevronDown, ChevronUp, Copy } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -17,6 +17,9 @@ import {
|
||||
highlightText,
|
||||
} from "./utils";
|
||||
|
||||
const COLLAPSE_THRESHOLD = 3000;
|
||||
const COLLAPSED_LENGTH = 1500;
|
||||
|
||||
interface SessionMessageItemProps {
|
||||
message: SessionMessage;
|
||||
isActive: boolean;
|
||||
@@ -31,6 +34,13 @@ export const SessionMessageItem = memo(function SessionMessageItem({
|
||||
onCopy,
|
||||
}: SessionMessageItemProps) {
|
||||
const { t } = useTranslation();
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
const isLong = message.content.length > COLLAPSE_THRESHOLD;
|
||||
const displayContent =
|
||||
isLong && !expanded
|
||||
? message.content.slice(0, COLLAPSED_LENGTH) + "…"
|
||||
: message.content;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -73,9 +83,35 @@ export const SessionMessageItem = memo(function SessionMessageItem({
|
||||
</div>
|
||||
<div className="whitespace-pre-wrap break-words [overflow-wrap:anywhere] text-sm leading-relaxed min-w-0">
|
||||
{searchQuery
|
||||
? highlightText(message.content, searchQuery)
|
||||
: message.content}
|
||||
? highlightText(displayContent, searchQuery)
|
||||
: displayContent}
|
||||
</div>
|
||||
{isLong && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setExpanded((v) => !v)}
|
||||
className="flex items-center gap-1 mt-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
{expanded ? (
|
||||
<>
|
||||
<ChevronUp className="size-3" />
|
||||
{t("sessionManager.collapseContent", {
|
||||
defaultValue: "收起",
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ChevronDown className="size-3" />
|
||||
{t("sessionManager.expandContent", {
|
||||
defaultValue: "展开完整内容",
|
||||
})}
|
||||
<span className="text-muted-foreground/60">
|
||||
({Math.round(message.content.length / 1000)}k)
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -725,7 +725,9 @@
|
||||
"copyCommand": "Copy Command",
|
||||
"copyMessage": "Copy Message",
|
||||
"messageCopied": "Message copied",
|
||||
"conversationHistory": "Conversation History"
|
||||
"conversationHistory": "Conversation History",
|
||||
"expandContent": "Expand full content",
|
||||
"collapseContent": "Collapse"
|
||||
},
|
||||
"console": {
|
||||
"providerSwitchReceived": "Received provider switch event:",
|
||||
|
||||
@@ -725,7 +725,9 @@
|
||||
"copyCommand": "コマンドをコピー",
|
||||
"copyMessage": "メッセージをコピー",
|
||||
"messageCopied": "メッセージがコピーされました",
|
||||
"conversationHistory": "会話履歴"
|
||||
"conversationHistory": "会話履歴",
|
||||
"expandContent": "全文を表示",
|
||||
"collapseContent": "折りたたむ"
|
||||
},
|
||||
"console": {
|
||||
"providerSwitchReceived": "プロバイダー切り替えイベントを受信:",
|
||||
|
||||
@@ -725,7 +725,9 @@
|
||||
"copyCommand": "复制命令",
|
||||
"copyMessage": "复制消息",
|
||||
"messageCopied": "已复制消息内容",
|
||||
"conversationHistory": "对话记录"
|
||||
"conversationHistory": "对话记录",
|
||||
"expandContent": "展开完整内容",
|
||||
"collapseContent": "收起"
|
||||
},
|
||||
"console": {
|
||||
"providerSwitchReceived": "收到供应商切换事件:",
|
||||
|
||||
Reference in New Issue
Block a user