diff --git a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx index 799acdf39..ced63a6f6 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/new-chat/[[...chat_id]]/page.tsx @@ -32,7 +32,6 @@ import { closeReportPanelAtom } from "@/atoms/chat/report-panel.atom"; import { membersAtom } from "@/atoms/members/members-query.atoms"; import { currentUserAtom } from "@/atoms/user/user-query.atoms"; import { Thread } from "@/components/assistant-ui/thread"; -import { ChatHeader } from "@/components/new-chat/chat-header"; import { ReportPanel } from "@/components/report-panel/report-panel"; import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking"; import { DisplayImageToolUI } from "@/components/tool-ui/display-image"; @@ -476,7 +475,7 @@ export default function NewChatPage() { const newThread = await createThread(searchSpaceId, initialTitle); currentThreadId = newThread.id; setThreadId(currentThreadId); - // Set currentThread so ChatHeader can show share button immediately + // Set currentThread so share button in header appears immediately setCurrentThread(newThread); // Track chat creation @@ -1670,10 +1669,9 @@ export default function NewChatPage() { {/* Disabled for now */}
- } - /> +
diff --git a/surfsense_web/components/assistant-ui/thread.tsx b/surfsense_web/components/assistant-ui/thread.tsx index 483ca2133..53e7f7eb6 100644 --- a/surfsense_web/components/assistant-ui/thread.tsx +++ b/surfsense_web/components/assistant-ui/thread.tsx @@ -79,18 +79,17 @@ const CYCLING_PLACEHOLDERS = [ interface ThreadProps { messageThinkingSteps?: Map; - header?: React.ReactNode; } -export const Thread: FC = ({ messageThinkingSteps = new Map(), header }) => { +export const Thread: FC = ({ messageThinkingSteps = new Map() }) => { return ( - + ); }; -const ThreadContent: FC<{ header?: React.ReactNode }> = ({ header }) => { +const ThreadContent: FC = () => { const showGutter = useAtomValue(showCommentsGutterAtom); return ( @@ -108,8 +107,6 @@ const ThreadContent: FC<{ header?: React.ReactNode }> = ({ header }) => { showGutter && "lg:pr-30" )} > - {header &&
{header}
} - thread.isEmpty}> diff --git a/surfsense_web/components/layout/ui/header/Header.tsx b/surfsense_web/components/layout/ui/header/Header.tsx index 1f04a347b..166bf6ed0 100644 --- a/surfsense_web/components/layout/ui/header/Header.tsx +++ b/surfsense_web/components/layout/ui/header/Header.tsx @@ -3,6 +3,8 @@ import { useAtomValue } from "jotai"; import { usePathname } from "next/navigation"; 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 type { ChatVisibility, ThreadRecord } from "@/lib/chat/thread-persistence"; @@ -12,23 +14,19 @@ interface HeaderProps { export function Header({ mobileMenuTrigger }: HeaderProps) { const pathname = usePathname(); + const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom); - // Check if we're on a chat page const isChatPage = pathname?.includes("/new-chat") ?? false; - // Use Jotai atom for thread state (synced from chat page) 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; - // Create minimal thread object for ChatShareButton (used for API calls) const threadForButton: ThreadRecord | null = hasThread && currentThreadState.id !== null ? { id: currentThreadState.id, visibility: currentThreadState.visibility ?? "PRIVATE", - // These fields are not used by ChatShareButton for display, only for checks created_by_id: null, search_space_id: 0, title: "", @@ -38,21 +36,20 @@ export function Header({ mobileMenuTrigger }: HeaderProps) { } : null; - const handleVisibilityChange = (_visibility: ChatVisibility) => { - // Visibility change is handled by ChatShareButton internally via Jotai - // This callback can be used for additional side effects if needed - }; + const handleVisibilityChange = (_visibility: ChatVisibility) => {}; return ( -
- {/* Left side - Mobile menu trigger */} +
+ {/* Left side - Mobile menu trigger + Model selector */}
{mobileMenuTrigger} + {isChatPage && searchSpaceId && ( + + )}
{/* Right side - Actions */}
- {/* Share button - only show on chat pages when thread exists */} {hasThread && ( )} diff --git a/surfsense_web/components/new-chat/chat-header.tsx b/surfsense_web/components/new-chat/chat-header.tsx index 2f1d9d845..4d40bc21a 100644 --- a/surfsense_web/components/new-chat/chat-header.tsx +++ b/surfsense_web/components/new-chat/chat-header.tsx @@ -13,9 +13,10 @@ import { ModelSelector } from "./model-selector"; interface ChatHeaderProps { searchSpaceId: number; + className?: string; } -export function ChatHeader({ searchSpaceId }: ChatHeaderProps) { +export function ChatHeader({ searchSpaceId, className }: ChatHeaderProps) { // LLM config sidebar state const [sidebarOpen, setSidebarOpen] = useState(false); const [selectedConfig, setSelectedConfig] = useState< @@ -85,6 +86,7 @@ export function ChatHeader({ searchSpaceId }: ChatHeaderProps) { onAddNewLLM={handleAddNewLLM} onEditImage={handleEditImageConfig} onAddNewImage={handleAddImageModel} + className={className} />