({
userId = "demo-user-id",
clerkUser = null,
desktopUser = {
id: "demo-user-id",
email: "demo@example.com",
name: "Demo User",
},
onSignOut = () => {},
onToggleSidebar,
isMobileFullscreen = false,
onChatSelect,
}: AgentsSidebarProps)
| 1651 | }) |
| 1652 | |
| 1653 | export function AgentsSidebar({ |
| 1654 | userId = "demo-user-id", |
| 1655 | clerkUser = null, |
| 1656 | desktopUser = { |
| 1657 | id: "demo-user-id", |
| 1658 | email: "demo@example.com", |
| 1659 | name: "Demo User", |
| 1660 | }, |
| 1661 | onSignOut = () => {}, |
| 1662 | onToggleSidebar, |
| 1663 | isMobileFullscreen = false, |
| 1664 | onChatSelect, |
| 1665 | }: AgentsSidebarProps) { |
| 1666 | const [selectedChatId, setSelectedChatId] = useAtom(selectedAgentChatIdAtom) |
| 1667 | const [selectedChatIsRemote, setSelectedChatIsRemote] = useAtom(selectedChatIsRemoteAtom) |
| 1668 | const previousChatId = useAtomValue(previousAgentChatIdAtom) |
| 1669 | const autoAdvanceTarget = useAtomValue(autoAdvanceTargetAtom) |
| 1670 | const [selectedDraftId, setSelectedDraftId] = useAtom(selectedDraftIdAtom) |
| 1671 | const setShowNewChatForm = useSetAtom(showNewChatFormAtom) |
| 1672 | const setDesktopView = useSetAtom(desktopViewAtom) |
| 1673 | const [loadingSubChats] = useAtom(loadingSubChatsAtom) |
| 1674 | const pendingQuestions = useAtomValue(pendingUserQuestionsAtom) |
| 1675 | // Use ref instead of state to avoid re-renders on hover |
| 1676 | const isSidebarHoveredRef = useRef(false) |
| 1677 | const closeButtonRef = useRef<HTMLDivElement>(null) |
| 1678 | const [searchQuery, setSearchQuery] = useState("") |
| 1679 | const [focusedChatIndex, setFocusedChatIndex] = useState<number>(-1) // -1 means no focus |
| 1680 | const hoveredChatIndexRef = useRef<number>(-1) // Track hovered chat for X hotkey - ref to avoid re-renders |
| 1681 | |
| 1682 | // Global desktop/fullscreen state from atoms (initialized in AgentsLayout) |
| 1683 | const isDesktop = useAtomValue(isDesktopAtom) |
| 1684 | const isFullscreen = useAtomValue(isFullscreenAtom) |
| 1685 | |
| 1686 | // Multi-select state |
| 1687 | const [selectedChatIds, setSelectedChatIds] = useAtom( |
| 1688 | selectedAgentChatIdsAtom, |
| 1689 | ) |
| 1690 | const isMultiSelectMode = useAtomValue(isAgentMultiSelectModeAtom) |
| 1691 | const selectedChatsCount = useAtomValue(selectedAgentChatsCountAtom) |
| 1692 | const toggleChatSelection = useSetAtom(toggleAgentChatSelectionAtom) |
| 1693 | const selectAllChats = useSetAtom(selectAllAgentChatsAtom) |
| 1694 | const clearChatSelection = useSetAtom(clearAgentChatSelectionAtom) |
| 1695 | |
| 1696 | // Scroll gradient refs - use DOM manipulation to avoid re-renders |
| 1697 | const topGradientRef = useRef<HTMLDivElement>(null) |
| 1698 | const bottomGradientRef = useRef<HTMLDivElement>(null) |
| 1699 | const scrollContainerRef = useRef<HTMLDivElement>(null) |
| 1700 | |
| 1701 | // Multiple drafts state - uses event-based sync instead of polling |
| 1702 | const drafts = useNewChatDrafts() |
| 1703 | |
| 1704 | // Read unseen changes from global atoms |
| 1705 | const unseenChanges = useAtomValue(agentsUnseenChangesAtom) |
| 1706 | const justCreatedIds = useAtomValue(justCreatedIdsAtom) |
| 1707 | |
| 1708 | // Haptic feedback |
| 1709 | const { trigger: triggerHaptic } = useHaptic() |
| 1710 |
nothing calls this directly
no test coverage detected