mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-09 15:52:40 +02:00
refactor: remove ChatHeader from Thread component and update related logic, improving code clarity and maintaining consistent header display in chat interface
This commit is contained in:
parent
662f4db13d
commit
8d5d8e490c
4 changed files with 19 additions and 25 deletions
|
|
@ -32,7 +32,6 @@ import { closeReportPanelAtom } from "@/atoms/chat/report-panel.atom";
|
||||||
import { membersAtom } from "@/atoms/members/members-query.atoms";
|
import { membersAtom } from "@/atoms/members/members-query.atoms";
|
||||||
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
|
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
|
||||||
import { Thread } from "@/components/assistant-ui/thread";
|
import { Thread } from "@/components/assistant-ui/thread";
|
||||||
import { ChatHeader } from "@/components/new-chat/chat-header";
|
|
||||||
import { ReportPanel } from "@/components/report-panel/report-panel";
|
import { ReportPanel } from "@/components/report-panel/report-panel";
|
||||||
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
|
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
|
||||||
import { DisplayImageToolUI } from "@/components/tool-ui/display-image";
|
import { DisplayImageToolUI } from "@/components/tool-ui/display-image";
|
||||||
|
|
@ -476,7 +475,7 @@ export default function NewChatPage() {
|
||||||
const newThread = await createThread(searchSpaceId, initialTitle);
|
const newThread = await createThread(searchSpaceId, initialTitle);
|
||||||
currentThreadId = newThread.id;
|
currentThreadId = newThread.id;
|
||||||
setThreadId(currentThreadId);
|
setThreadId(currentThreadId);
|
||||||
// Set currentThread so ChatHeader can show share button immediately
|
// Set currentThread so share button in header appears immediately
|
||||||
setCurrentThread(newThread);
|
setCurrentThread(newThread);
|
||||||
|
|
||||||
// Track chat creation
|
// Track chat creation
|
||||||
|
|
@ -1672,7 +1671,6 @@ export default function NewChatPage() {
|
||||||
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||||||
<Thread
|
<Thread
|
||||||
messageThinkingSteps={messageThinkingSteps}
|
messageThinkingSteps={messageThinkingSteps}
|
||||||
header={<ChatHeader searchSpaceId={searchSpaceId} />}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ReportPanel />
|
<ReportPanel />
|
||||||
|
|
|
||||||
|
|
@ -79,18 +79,17 @@ const CYCLING_PLACEHOLDERS = [
|
||||||
|
|
||||||
interface ThreadProps {
|
interface ThreadProps {
|
||||||
messageThinkingSteps?: Map<string, ThinkingStep[]>;
|
messageThinkingSteps?: Map<string, ThinkingStep[]>;
|
||||||
header?: React.ReactNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Thread: FC<ThreadProps> = ({ messageThinkingSteps = new Map(), header }) => {
|
export const Thread: FC<ThreadProps> = ({ messageThinkingSteps = new Map() }) => {
|
||||||
return (
|
return (
|
||||||
<ThinkingStepsContext.Provider value={messageThinkingSteps}>
|
<ThinkingStepsContext.Provider value={messageThinkingSteps}>
|
||||||
<ThreadContent header={header} />
|
<ThreadContent />
|
||||||
</ThinkingStepsContext.Provider>
|
</ThinkingStepsContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ThreadContent: FC<{ header?: React.ReactNode }> = ({ header }) => {
|
const ThreadContent: FC = () => {
|
||||||
const showGutter = useAtomValue(showCommentsGutterAtom);
|
const showGutter = useAtomValue(showCommentsGutterAtom);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -108,8 +107,6 @@ const ThreadContent: FC<{ header?: React.ReactNode }> = ({ header }) => {
|
||||||
showGutter && "lg:pr-30"
|
showGutter && "lg:pr-30"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{header && <div className="sticky top-0 z-10 mb-4">{header}</div>}
|
|
||||||
|
|
||||||
<AssistantIf condition={({ thread }) => thread.isEmpty}>
|
<AssistantIf condition={({ thread }) => thread.isEmpty}>
|
||||||
<ThreadWelcome />
|
<ThreadWelcome />
|
||||||
</AssistantIf>
|
</AssistantIf>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { currentThreadAtom } from "@/atoms/chat/current-thread.atom";
|
import { currentThreadAtom } from "@/atoms/chat/current-thread.atom";
|
||||||
|
import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||||
|
import { ChatHeader } from "@/components/new-chat/chat-header";
|
||||||
import { ChatShareButton } from "@/components/new-chat/chat-share-button";
|
import { ChatShareButton } from "@/components/new-chat/chat-share-button";
|
||||||
import type { ChatVisibility, ThreadRecord } from "@/lib/chat/thread-persistence";
|
import type { ChatVisibility, ThreadRecord } from "@/lib/chat/thread-persistence";
|
||||||
|
|
||||||
|
|
@ -12,23 +14,19 @@ interface HeaderProps {
|
||||||
|
|
||||||
export function Header({ mobileMenuTrigger }: HeaderProps) {
|
export function Header({ mobileMenuTrigger }: HeaderProps) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||||
|
|
||||||
// Check if we're on a chat page
|
|
||||||
const isChatPage = pathname?.includes("/new-chat") ?? false;
|
const isChatPage = pathname?.includes("/new-chat") ?? false;
|
||||||
|
|
||||||
// Use Jotai atom for thread state (synced from chat page)
|
|
||||||
const currentThreadState = useAtomValue(currentThreadAtom);
|
const currentThreadState = useAtomValue(currentThreadAtom);
|
||||||
|
|
||||||
// Show button only when we have a thread id (thread exists and is synced to Jotai)
|
|
||||||
const hasThread = isChatPage && currentThreadState.id !== null;
|
const hasThread = isChatPage && currentThreadState.id !== null;
|
||||||
|
|
||||||
// Create minimal thread object for ChatShareButton (used for API calls)
|
|
||||||
const threadForButton: ThreadRecord | null =
|
const threadForButton: ThreadRecord | null =
|
||||||
hasThread && currentThreadState.id !== null
|
hasThread && currentThreadState.id !== null
|
||||||
? {
|
? {
|
||||||
id: currentThreadState.id,
|
id: currentThreadState.id,
|
||||||
visibility: currentThreadState.visibility ?? "PRIVATE",
|
visibility: currentThreadState.visibility ?? "PRIVATE",
|
||||||
// These fields are not used by ChatShareButton for display, only for checks
|
|
||||||
created_by_id: null,
|
created_by_id: null,
|
||||||
search_space_id: 0,
|
search_space_id: 0,
|
||||||
title: "",
|
title: "",
|
||||||
|
|
@ -38,21 +36,20 @@ export function Header({ mobileMenuTrigger }: HeaderProps) {
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const handleVisibilityChange = (_visibility: ChatVisibility) => {
|
const handleVisibilityChange = (_visibility: ChatVisibility) => {};
|
||||||
// Visibility change is handled by ChatShareButton internally via Jotai
|
|
||||||
// This callback can be used for additional side effects if needed
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="sticky top-0 z-10 flex h-14 shrink-0 items-center gap-2 border-b bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60 px-4">
|
<header className="sticky top-0 z-10 flex h-14 shrink-0 items-center gap-2 bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60 px-4">
|
||||||
{/* Left side - Mobile menu trigger */}
|
{/* Left side - Mobile menu trigger + Model selector */}
|
||||||
<div className="flex flex-1 items-center gap-2 min-w-0">
|
<div className="flex flex-1 items-center gap-2 min-w-0">
|
||||||
{mobileMenuTrigger}
|
{mobileMenuTrigger}
|
||||||
|
{isChatPage && searchSpaceId && (
|
||||||
|
<ChatHeader searchSpaceId={Number(searchSpaceId)} className="md:h-9 md:px-4 md:text-sm" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right side - Actions */}
|
{/* Right side - Actions */}
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{/* Share button - only show on chat pages when thread exists */}
|
|
||||||
{hasThread && (
|
{hasThread && (
|
||||||
<ChatShareButton thread={threadForButton} onVisibilityChange={handleVisibilityChange} />
|
<ChatShareButton thread={threadForButton} onVisibilityChange={handleVisibilityChange} />
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,10 @@ import { ModelSelector } from "./model-selector";
|
||||||
|
|
||||||
interface ChatHeaderProps {
|
interface ChatHeaderProps {
|
||||||
searchSpaceId: number;
|
searchSpaceId: number;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChatHeader({ searchSpaceId }: ChatHeaderProps) {
|
export function ChatHeader({ searchSpaceId, className }: ChatHeaderProps) {
|
||||||
// LLM config sidebar state
|
// LLM config sidebar state
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||||
const [selectedConfig, setSelectedConfig] = useState<
|
const [selectedConfig, setSelectedConfig] = useState<
|
||||||
|
|
@ -85,6 +86,7 @@ export function ChatHeader({ searchSpaceId }: ChatHeaderProps) {
|
||||||
onAddNewLLM={handleAddNewLLM}
|
onAddNewLLM={handleAddNewLLM}
|
||||||
onEditImage={handleEditImageConfig}
|
onEditImage={handleEditImageConfig}
|
||||||
onAddNewImage={handleAddImageModel}
|
onAddNewImage={handleAddImageModel}
|
||||||
|
className={className}
|
||||||
/>
|
/>
|
||||||
<ModelConfigSidebar
|
<ModelConfigSidebar
|
||||||
open={sidebarOpen}
|
open={sidebarOpen}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue