import React, { MouseEventHandler, forwardRef, useMemo, useRef, useState } from 'react'; import { useAtom, useAtomValue } from 'jotai'; import { Avatar, Box, Button, Icon, IconButton, Icons, Menu, MenuItem, PopOut, RectCords, Text, config, toRem, } from 'folds'; import { useVirtualizer } from '@tanstack/react-virtual'; import FocusTrap from 'focus-trap-react'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { factoryRoomIdByActivity } from '../../../utils/sort'; import { NavButton, NavCategory, NavCategoryHeader, NavEmptyCenter, NavEmptyLayout, NavItem, NavItemContent, } from '../../../components/nav'; import { getDirectRoomPath } from '../../pathUtils'; import { getCanonicalAliasOrRoomId } from '../../../utils/matrix'; import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom'; import { VirtualTile } from '../../../components/virtualizer'; import { RoomNavCategoryButton, RoomNavItem } from '../../../features/room-nav'; import { makeNavCategoryId } from '../../../state/closedNavCategories'; import { roomToUnreadAtom } from '../../../state/room/roomToUnread'; import { useCategoryHandler } from '../../../hooks/useCategoryHandler'; import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper'; import { useDirectRooms } from './useDirectRooms'; import { openInviteUser } from '../../../../client/action/navigation'; import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page'; import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories'; import { useRoomsUnread } from '../../../state/hooks/unread'; import { markAsRead } from '../../../../client/action/notifications'; import { stopPropagation } from '../../../utils/keyboard'; import { useSetting } from '../../../state/hooks/settings'; import { settingsAtom } from '../../../state/settings'; import { getRoomNotificationMode, useRoomsNotificationPreferencesContext, } from '../../../hooks/useRoomsNotificationPreferences'; type DirectMenuProps = { requestClose: () => void; }; const DirectMenu = forwardRef(({ requestClose }, ref) => { const mx = useMatrixClient(); const [hideActivity] = useSetting(settingsAtom, 'hideActivity'); const orphanRooms = useDirectRooms(); const unread = useRoomsUnread(orphanRooms, roomToUnreadAtom); const handleMarkAsRead = () => { if (!unread) return; orphanRooms.forEach((rId) => markAsRead(mx, rId, hideActivity)); requestClose(); }; return ( } radii="300" aria-disabled={!unread} > Mark as Read ); }); function DirectHeader() { const [menuAnchor, setMenuAnchor] = useState(); const handleOpenMenu: MouseEventHandler = (evt) => { const cords = evt.currentTarget.getBoundingClientRect(); setMenuAnchor((currentState) => { if (currentState) return undefined; return cords; }); }; return ( <> Direct Messages setMenuAnchor(undefined), clickOutsideDeactivates: true, isKeyForward: (evt: KeyboardEvent) => evt.key === 'ArrowDown', isKeyBackward: (evt: KeyboardEvent) => evt.key === 'ArrowUp', escapeDeactivates: stopPropagation, }} > setMenuAnchor(undefined)} /> } /> ); } function DirectEmpty() { return ( } title={ No Direct Messages } content={ You do not have any direct messages yet. } options={ } /> ); } const DEFAULT_CATEGORY_ID = makeNavCategoryId('direct', 'direct'); export function Direct() { const mx = useMatrixClient(); useNavToActivePathMapper('direct'); const scrollRef = useRef(null); const directs = useDirectRooms(); const notificationPreferences = useRoomsNotificationPreferencesContext(); const roomToUnread = useAtomValue(roomToUnreadAtom); const selectedRoomId = useSelectedRoom(); const noRoomToDisplay = directs.length === 0; const [closedCategories, setClosedCategories] = useAtom(useClosedNavCategoriesAtom()); const sortedDirects = useMemo(() => { const items = Array.from(directs).sort(factoryRoomIdByActivity(mx)); if (closedCategories.has(DEFAULT_CATEGORY_ID)) { return items.filter((rId) => roomToUnread.has(rId) || rId === selectedRoomId); } return items; }, [mx, directs, closedCategories, roomToUnread, selectedRoomId]); const virtualizer = useVirtualizer({ count: sortedDirects.length, getScrollElement: () => scrollRef.current, estimateSize: () => 38, overscan: 10, }); const handleCategoryClick = useCategoryHandler(setClosedCategories, (categoryId) => closedCategories.has(categoryId) ); return ( {noRoomToDisplay ? ( ) : ( openInviteUser()}> Create Chat Chats
{virtualizer.getVirtualItems().map((vItem) => { const roomId = sortedDirects[vItem.index]; const room = mx.getRoom(roomId); if (!room) return null; const selected = selectedRoomId === roomId; return ( ); })}
)}
); }