diff --git a/surfsense_web/components/assistant-ui/thread.tsx b/surfsense_web/components/assistant-ui/thread.tsx index 763159b17..edc2c4bb3 100644 --- a/surfsense_web/components/assistant-ui/thread.tsx +++ b/surfsense_web/components/assistant-ui/thread.tsx @@ -25,6 +25,7 @@ import { SquareIcon, SquareLibrary, Upload, + X, } from "lucide-react"; import { useParams } from "next/navigation"; import { type FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; @@ -34,6 +35,7 @@ import { mentionedDocumentsAtom, sidebarSelectedDocumentsAtom, } from "@/atoms/chat/mentioned-documents.atom"; +import { connectorDialogOpenAtom } from "@/atoms/connector-dialog/connector-dialog.atoms"; import { connectorsAtom } from "@/atoms/connectors/connector-query.atoms"; import { documentTypeCountsAtom } from "@/atoms/documents/document-query.atoms"; import { documentsSidebarOpenAtom } from "@/atoms/documents/ui.atoms"; @@ -68,6 +70,7 @@ import { type DocumentMentionPickerRef, } from "@/components/new-chat/document-mention-picker"; import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking"; +import { Avatar, AvatarFallback, AvatarGroup } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { DropdownMenu, @@ -76,6 +79,7 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; +import { getConnectorIcon } from "@/contracts/enums/connectorIcons"; import type { Document } from "@/contracts/types/document.types"; import { useBatchCommentsPreload } from "@/hooks/use-comments"; import { useCommentsElectric } from "@/hooks/use-comments-electric"; @@ -233,6 +237,78 @@ const ThreadWelcome: FC = () => { ); }; +const BANNER_CONNECTORS = [ + { type: "GOOGLE_DRIVE_CONNECTOR", label: "Google Drive" }, + { type: "GOOGLE_GMAIL_CONNECTOR", label: "Gmail" }, + { type: "NOTION_CONNECTOR", label: "Notion" }, + { type: "YOUTUBE_CONNECTOR", label: "YouTube" }, + { type: "SLACK_CONNECTOR", label: "Slack" }, +] as const; + +const BANNER_DISMISSED_KEY = "surfsense-connect-tools-banner-dismissed"; + +const ConnectToolsBanner: FC = () => { + const { data: connectors } = useAtomValue(connectorsAtom); + const setConnectorDialogOpen = useSetAtom(connectorDialogOpenAtom); + const [dismissed, setDismissed] = useState(() => { + if (typeof window === "undefined") return false; + return localStorage.getItem(BANNER_DISMISSED_KEY) === "true"; + }); + + const hasConnectors = (connectors?.length ?? 0) > 0; + + if (dismissed || hasConnectors) return null; + + const handleDismiss = (e: React.MouseEvent) => { + e.stopPropagation(); + setDismissed(true); + localStorage.setItem(BANNER_DISMISSED_KEY, "true"); + }; + + return ( +
+ +
+ ); +}; + const Composer: FC = () => { // Document mention state (atoms persist across component remounts) const [mentionedDocuments, setMentionedDocuments] = useAtom(mentionedDocumentsAtom); @@ -440,9 +516,9 @@ const Composer: FC = () => { currentUserId={currentUser?.id ?? null} members={members ?? []} /> -
- {/* Inline editor with @mention support */} -
+
+ {/* Inline editor with @mention support */} +
{ document.body )} +
); @@ -529,7 +606,7 @@ const ComposerAction: FC = ({ isBlockedByOtherUser = false const isSendDisabled = isComposerEmpty || !hasModelConfigured || isBlockedByOtherUser; return ( -
+
diff --git a/surfsense_web/components/layout/ui/sidebar/SidebarSlideOutPanel.tsx b/surfsense_web/components/layout/ui/sidebar/SidebarSlideOutPanel.tsx index 0f243c6c0..126d0731a 100644 --- a/surfsense_web/components/layout/ui/sidebar/SidebarSlideOutPanel.tsx +++ b/surfsense_web/components/layout/ui/sidebar/SidebarSlideOutPanel.tsx @@ -49,17 +49,19 @@ export function SidebarSlideOutPanel({ {open && ( <> - {/* Backdrop overlay with blur — only covers the main content area (right of sidebar) */} - onOpenChange(false)} - aria-hidden="true" - /> + {/* Backdrop overlay with blur — desktop only, covers main content area (right of sidebar) */} + {!isMobile && ( + onOpenChange(false)} + aria-hidden="true" + /> + )} {/* Clip container - positioned at sidebar edge with overflow hidden */}