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 5d00232f6..fb84849e7 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 @@ -9,7 +9,6 @@ import { import { useQueryClient } from "@tanstack/react-query"; import { useAtomValue, useSetAtom } from "jotai"; import { useParams, useSearchParams } from "next/navigation"; -import { useTranslations } from "next-intl"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { toast } from "sonner"; import { z } from "zod"; @@ -39,7 +38,7 @@ import { GeneratePodcastToolUI } from "@/components/tool-ui/generate-podcast"; import { LinkPreviewToolUI } from "@/components/tool-ui/link-preview"; import { ScrapeWebpageToolUI } from "@/components/tool-ui/scrape-webpage"; import { RecallMemoryToolUI, SaveMemoryToolUI } from "@/components/tool-ui/user-memory"; -import { Spinner } from "@/components/ui/spinner"; +import { Skeleton } from "@/components/ui/skeleton"; import { useChatSessionStateSync } from "@/hooks/use-chat-session-state"; import { useMessagesElectric } from "@/hooks/use-messages-electric"; // import { WriteTodosToolUI } from "@/components/tool-ui/write-todos"; @@ -53,12 +52,10 @@ import { } from "@/lib/chat/podcast-state"; import { appendMessage, - type ChatVisibility, createThread, getRegenerateUrl, getThreadFull, getThreadMessages, - type MessageRecord, type ThreadRecord, } from "@/lib/chat/thread-persistence"; import { @@ -67,6 +64,7 @@ import { trackChatMessageSent, trackChatResponseReceived, } from "@/lib/posthog/events"; +import { documentsApiService } from "@/lib/apis/documents-api.service"; /** * Extract thinking steps from message content @@ -137,7 +135,6 @@ interface ThinkingStepData { } export default function NewChatPage() { - const t = useTranslations("dashboard"); const params = useParams(); const queryClient = useQueryClient(); const [isInitializing, setIsInitializing] = useState(true); @@ -329,6 +326,33 @@ export default function NewChatPage() { initializeThread(); }, [initializeThread]); + // Prefetch document titles for @ mention picker + // Runs when user lands on page so data is ready when they type @ + useEffect(() => { + if (!searchSpaceId) return; + + const prefetchParams = { + search_space_id: searchSpaceId, + page: 0, + page_size: 20, + }; + + queryClient.prefetchQuery({ + queryKey: ["document-titles", prefetchParams], + queryFn: () => documentsApiService.searchDocumentTitles({ queryParams: prefetchParams }), + staleTime: 60 * 1000, + }); + + queryClient.prefetchQuery({ + queryKey: ["surfsense-docs-mention", "", false], + queryFn: () => + documentsApiService.getSurfsenseDocs({ + queryParams: { page: 0, page_size: 20 }, + }), + staleTime: 3 * 60 * 1000, + }); + }, [searchSpaceId, queryClient]); + // Handle scroll to comment from URL query params (e.g., from inbox item click) const searchParams = useSearchParams(); const targetCommentIdParam = searchParams.get("commentId"); @@ -366,20 +390,7 @@ export default function NewChatPage() { } setIsRunning(false); }, []); - - // Handle visibility change from ChatShareButton - const handleVisibilityChange = useCallback( - (newVisibility: ChatVisibility) => { - setCurrentThread((prev) => (prev ? { ...prev, visibility: newVisibility } : null)); - // Refetch all thread queries so sidebar reflects the change immediately - // Use predicate to match any query that starts with "threads" - queryClient.refetchQueries({ - predicate: (query) => Array.isArray(query.queryKey) && query.queryKey[0] === "threads", - }); - }, - [queryClient] - ); - + // Handle new message from user const onNew = useCallback( async (message: AppendMessage) => { @@ -1347,7 +1358,7 @@ export default function NewChatPage() { // Handle reloading/refreshing the last AI response const onReload = useCallback( - async (parentId: string | null) => { + async () => { // parentId is the ID of the message to reload from (the user message) // We call regenerate without a query to use the same query await handleRegenerate(null); @@ -1372,9 +1383,39 @@ export default function NewChatPage() { // Show loading state only when loading an existing thread if (isInitializing) { return ( -