fix(workspace): control history rendering and preview sizing
This commit is contained in:
parent
b30cbd2a3b
commit
ffd10063a9
|
|
@ -50,3 +50,4 @@ frontend/imports
|
|||
# ignore the legacy `web` folder
|
||||
web/
|
||||
memo.md
|
||||
.codex
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ export default function ChatPage() {
|
|||
} = useArtifacts();
|
||||
const { threadId, isNewThread, setIsNewThread, isMock } = useThreadChat();
|
||||
const searchParams = useSearchParams();
|
||||
// History render rules:
|
||||
// - /workspace/chats/{thread_id}: always render history
|
||||
// - /workspace/chats/new: render history only when xclaw_used=true
|
||||
const shouldRenderHistory =
|
||||
!isNewThread ||
|
||||
searchParams.get("xclaw_used")?.trim().toLowerCase() === "true";
|
||||
|
||||
// Submission strategy:
|
||||
// - xclaw_used=true: follow `isnew` (isnew=false => reuse existing thread)
|
||||
|
|
@ -65,6 +71,13 @@ export default function ChatPage() {
|
|||
if (!isNewThread) {
|
||||
return false;
|
||||
}
|
||||
const queryThreadId = searchParams.get("thread_id")?.trim();
|
||||
const reuseExistingThread =
|
||||
!!queryThreadId &&
|
||||
searchParams.get("isnew")?.trim().toLowerCase() === "false";
|
||||
if (reuseExistingThread) {
|
||||
return false;
|
||||
}
|
||||
if (searchParams.get("xclaw_used")?.trim().toLowerCase() !== "true") {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -115,6 +128,22 @@ export default function ChatPage() {
|
|||
|
||||
const [hasSubmitted, setHasSubmitted] = useState(false);
|
||||
const showInputBox = !(isNewThread && thread.isThreadLoading);
|
||||
const [historyCutoff, setHistoryCutoff] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldRenderHistory) {
|
||||
setHistoryCutoff(null);
|
||||
return;
|
||||
}
|
||||
if (historyCutoff === null && !thread.isThreadLoading) {
|
||||
setHistoryCutoff(thread.messages.length);
|
||||
}
|
||||
}, [
|
||||
historyCutoff,
|
||||
shouldRenderHistory,
|
||||
thread.isThreadLoading,
|
||||
thread.messages.length,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const pageTitle = isNewThread
|
||||
|
|
@ -231,7 +260,7 @@ export default function ChatPage() {
|
|||
)}
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-2 overflow-hidden">
|
||||
<TokenUsageIndicator messages={thread.messages} />
|
||||
{/* <TokenUsageIndicator messages={thread.messages} /> */}
|
||||
<DevTodoList
|
||||
className="bg-white"
|
||||
todos={thread.values.todos ?? []}
|
||||
|
|
@ -280,6 +309,11 @@ export default function ChatPage() {
|
|||
)}
|
||||
threadId={threadId}
|
||||
thread={thread}
|
||||
messagesOverride={
|
||||
shouldRenderHistory || historyCutoff === null
|
||||
? undefined
|
||||
: thread.messages.slice(historyCutoff)
|
||||
}
|
||||
paddingBottom={todoListCollapsed ? 160 : 280}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -142,6 +142,6 @@ export const ArtifactContent = ({
|
|||
}: ArtifactContentProps) => (
|
||||
<div className="min-h-0 flex-1 overflow-auto rounded-[10px]">
|
||||
{/* <div className={cn("mb-[207px]! p-4", className)} {...props} /> */}
|
||||
<div className={cn("mb-[150px] h-full p-4", className)} {...props} />
|
||||
<div className={cn("mb-[150px] min-h-full p-4", className)} {...props} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -527,11 +527,11 @@ export function ArtifactFilePreview({
|
|||
if (language === "markdown") {
|
||||
return (
|
||||
<div
|
||||
className={cn("size-full p-[20px]")}
|
||||
className={cn("w-full p-[20px]")}
|
||||
style={{ "--zoom-scale": zoomScale } as React.CSSProperties}
|
||||
>
|
||||
<Streamdown
|
||||
className="size-full"
|
||||
className="w-full"
|
||||
{...streamdownPlugins}
|
||||
components={{ a: CitationLink }}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -3,22 +3,22 @@
|
|||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { uuid } from "@/core/utils/uuid";
|
||||
|
||||
export function useThreadChat() {
|
||||
const { thread_id: threadIdFromPath } = useParams<{ thread_id: string }>();
|
||||
const pathname = usePathname();
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const xClawUsedFromQuery = searchParams.get("xclaw_used");
|
||||
const isNewFromQuery =
|
||||
searchParams.get("isnew")?.trim().toLowerCase() === "false";
|
||||
const queryThreadIdFromParams = searchParams.get("thread_id")?.trim();
|
||||
const shouldUseQueryThreadId =
|
||||
pathname.startsWith("/workspace/chats/") &&
|
||||
!!queryThreadIdFromParams &&
|
||||
(xClawUsedFromQuery === "true" || isNewFromQuery);
|
||||
const [threadId, setThreadId] = useState(() => {
|
||||
if (threadIdFromPath === "new") {
|
||||
const shouldUseQueryThreadId = pathname.startsWith("/workspace/chats/");
|
||||
const queryThreadId =
|
||||
shouldUseQueryThreadId && xClawUsedFromQuery === "true"
|
||||
? searchParams.get("thread_id")?.trim()
|
||||
: undefined;
|
||||
return queryThreadId ?? uuid();
|
||||
return shouldUseQueryThreadId ? queryThreadIdFromParams : undefined;
|
||||
}
|
||||
return threadIdFromPath;
|
||||
});
|
||||
|
|
@ -30,12 +30,15 @@ export function useThreadChat() {
|
|||
useEffect(() => {
|
||||
if (pathname.endsWith("/new")) {
|
||||
setIsNewThread(true);
|
||||
const shouldUseQueryThreadId = pathname.startsWith("/workspace/chats/");
|
||||
const queryThreadId =
|
||||
shouldUseQueryThreadId && xClawUsedFromQuery === "true"
|
||||
? searchParams.get("thread_id")?.trim()
|
||||
: undefined;
|
||||
setThreadId(queryThreadId ?? uuid());
|
||||
const nextQueryThreadId = searchParams.get("thread_id")?.trim();
|
||||
const nextIsNewFromQuery =
|
||||
searchParams.get("isnew")?.trim().toLowerCase() === "false";
|
||||
const nextXClawUsed = searchParams.get("xclaw_used");
|
||||
const nextShouldUseQueryThreadId =
|
||||
pathname.startsWith("/workspace/chats/") &&
|
||||
!!nextQueryThreadId &&
|
||||
(nextXClawUsed === "true" || nextIsNewFromQuery);
|
||||
setThreadId(nextShouldUseQueryThreadId ? nextQueryThreadId : undefined);
|
||||
return;
|
||||
}
|
||||
setIsNewThread(false);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ export function useIframeSkill(): UseIframeSkillReturn {
|
|||
|
||||
// 0. 监听 query 中 XClawUsed=true 且带 thread_id 时跳转并清理 query
|
||||
useEffect(() => {
|
||||
console.log(xClawUsedFromQuery, threadIdFromQuery, lastThreadIdRef.current);
|
||||
|
||||
if (!threadIdFromQuery) return;
|
||||
if (xClawUsedFromQuery !== "true") return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue