91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
"use client";
|
||
|
||
import { useParams, usePathname, useSearchParams } from "next/navigation";
|
||
import { useEffect, useState } from "react";
|
||
|
||
|
||
export function useThreadChat() {
|
||
const pathname = usePathname();
|
||
const params = useParams<{ thread_id: string }>();
|
||
const searchParams = useSearchParams();
|
||
const threadIdFromSearchParams = searchParams.get("thread_id")?.trim();
|
||
// showWelcomeStyle的子判断
|
||
const isChattingFromQuery = (() => {
|
||
const isChatting = searchParams.get("is_chatting");
|
||
return isChatting === "true";
|
||
})();
|
||
// 兜底:当 params 还未就绪时,从 pathname 解析 thread_id。
|
||
const threadIdFromPathname = (() => {
|
||
const parts = pathname.split("?")[0]?.split("/") ?? [];
|
||
const idx = parts.lastIndexOf("chats");
|
||
if (idx >= 0 && parts.length > idx + 1) {
|
||
return parts[idx + 1];
|
||
}
|
||
return undefined;
|
||
})();
|
||
const rawPathThreadId = params?.thread_id ?? threadIdFromPathname;
|
||
|
||
const isNewRoute = rawPathThreadId === "new";
|
||
const threadIdFromPathOrParams = isNewRoute
|
||
? normalizeThreadId(threadIdFromSearchParams)
|
||
: normalizeThreadId(rawPathThreadId);
|
||
// console.log("[useThreadChat] pathname", pathname);
|
||
// console.log("[useThreadChat] params.thread_id", params?.thread_id);
|
||
// console.log("[useThreadChat] threadIdFromPathname", threadIdFromPathname);
|
||
// console.log("[useThreadChat] threadIdFromPath", threadIdFromPath);
|
||
// New session is only controlled by `/workspace/chats/new`.
|
||
const [isNewThread, setIsNewThread] = useState(() => isNewRoute);
|
||
|
||
const [showWelcomeStyle, setShowWelcomeStyle] = useState(() => {
|
||
return isNewRoute || !isChattingFromQuery;
|
||
});
|
||
// console.log("[useThreadChat] effectiveThreadIdFromPath", effectiveThreadIdFromPath);
|
||
|
||
const [threadId, setThreadId] = useState<string>(() => {
|
||
return threadIdFromPathOrParams ?? "";
|
||
});
|
||
|
||
|
||
useEffect(() => {
|
||
// 记住最近一次有效的 thread_id,供下次加载兜底使用。
|
||
if (threadId && threadId !== "new" && typeof window !== "undefined") {
|
||
window.sessionStorage.setItem("workspace.thread_id", threadId);
|
||
}
|
||
setIsNewThread(isNewRoute);
|
||
// Prefer path thread id, fall back to query thread_id when path is /new.
|
||
setThreadId(threadIdFromPathOrParams ?? "");
|
||
setShowWelcomeStyle(isNewRoute || !isChattingFromQuery);
|
||
}, [
|
||
isNewRoute,
|
||
pathname,
|
||
searchParams,
|
||
isChattingFromQuery,
|
||
threadId,
|
||
threadIdFromPathOrParams,
|
||
]);
|
||
const isMock = searchParams.get("mock") === "true";
|
||
return {
|
||
threadId,
|
||
isNewThread,
|
||
setIsNewThread,
|
||
isMock,
|
||
showWelcomeStyle,
|
||
};
|
||
}
|
||
|
||
function normalizeThreadId(value?: string | null): string | undefined {
|
||
if (!value) return undefined;
|
||
return isValidThreadId(value) ? value.trim() : undefined;
|
||
}
|
||
|
||
function isValidThreadId(value?: string | null): value is string {
|
||
if (!value) return false;
|
||
const normalized = value.trim().toLowerCase();
|
||
return (
|
||
normalized.length > 0 &&
|
||
normalized !== "new" &&
|
||
normalized !== "undefined" &&
|
||
normalized !== "null"
|
||
);
|
||
}
|