import FocusTrap from 'focus-trap-react'; import { Avatar, Box, config, Icon, Icons, Input, Line, MenuItem, Modal, Overlay, OverlayCenter, Scroll, Text, toRem, } from 'folds'; import React, { useCallback } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { isKeyHotkey } from 'is-hotkey'; import { useAtom } from 'jotai'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { RoomAvatar, RoomIcon } from '../../components/room-avatar'; import { getAllParents, getDirectRoomAvatarUrl, getRoomAvatarUrl, guessPerfectParent, } from '../../utils/room'; import { highlightText } from '../../plugins/react-custom-html-parser'; import { nameInitials } from '../../utils/common'; import { useRoomNavigate } from '../../hooks/useRoomNavigate'; import { getMxIdLocalPart, getMxIdServer } from '../../utils/matrix'; import { UnreadBadge, UnreadBadgeCenter } from '../../components/unread-badge'; import { searchModalAtom } from '../../state/searchModal'; import { useKeyDown } from '../../hooks/useKeyDown'; import { useMediaAuthentication } from '../../hooks/useMediaAuthentication'; import { KeySymbol } from '../../utils/key-symbol'; import { isMacOS } from '../../utils/user-agent'; import { getDmUserId, useRoomSearch } from './useRoomSearch'; type SearchProps = { requestClose: () => void; }; export function Search({ requestClose }: SearchProps) { const { t } = useTranslation(); const mx = useMatrixClient(); const useAuthentication = useMediaAuthentication(); const { navigateRoom, navigateSpace } = useRoomNavigate(); const openRoomId = useCallback( (roomId: string, isSpace: boolean) => { if (isSpace) navigateSpace(roomId); else navigateRoom(roomId); requestClose(); }, [navigateRoom, navigateSpace, requestClose] ); const { inputRef, scrollRef, roomsToRender, result, listFocus, queryHighlightRegex, handleInputChange, handleInputKeyDown, handleRoomClick, getRoom, mDirects, orphanSpaces, roomToParents, roomToUnread, myUserId, } = useRoomSearch({ onOpenRoomId: openRoomId }); return ( inputRef.current, returnFocusOnDeactivate: false, allowOutsideClick: true, clickOutsideDeactivates: true, onDeactivate: requestClose, escapeDeactivates: (evt) => { evt.stopPropagation(); return true; }, }} > } onChange={handleInputChange} onKeyDown={handleInputKeyDown} /> {roomsToRender.length === 0 && ( {result ? t('Search.no_match_found') : t('Search.no_rooms')} {result ? t('Search.no_match_for_query', { query: result.query }) : t('Search.no_rooms_to_display')} )} {roomsToRender.length > 0 && (
{roomsToRender.map((roomId, index) => { const room = getRoom(roomId); if (!room) return null; const dm = mDirects.has(roomId); const dmUserId = dm ? getDmUserId(roomId, getRoom, myUserId) : undefined; const dmUsername = dmUserId ? getMxIdLocalPart(dmUserId) : undefined; const dmUserServer = dmUserId ? getMxIdServer(dmUserId) : undefined; const allParents = getAllParents(roomToParents, roomId); const orphanParents = allParents ? orphanSpaces.filter((o) => allParents.has(o)) : undefined; const perfectOrphanParent = orphanParents && guessPerfectParent(mx, roomId, orphanParents); const exactParents = roomToParents.get(roomId); const perfectParent = exactParents && guessPerfectParent(mx, roomId, Array.from(exactParents)); const unread = roomToUnread.get(roomId); return ( {dmUserServer && ( {dmUserServer} )} {!dm && perfectOrphanParent && ( {getRoom(perfectOrphanParent)?.name ?? perfectOrphanParent} )} {unread && ( 0} count={unread.total} /> )} } before={ {dm || room.isSpaceRoom() ? ( ( {nameInitials(room.name)} )} /> ) : ( )} } > {queryHighlightRegex ? highlightText(queryHighlightRegex, [room.name]) : room.name} {dmUsername && ( @ {queryHighlightRegex ? highlightText(queryHighlightRegex, [dmUsername]) : dmUsername} )} {!dm && perfectParent && perfectParent !== perfectOrphanParent && ( — {getRoom(perfectParent)?.name ?? perfectParent} )} ); })}
)}
}} />
); } export function SearchModalRenderer() { const [opened, setOpen] = useAtom(searchModalAtom); useKeyDown( window, useCallback( (event) => { if (isKeyHotkey('mod+k', event)) { event.preventDefault(); if (opened) { setOpen(false); return; } const portalContainer = document.getElementById('portalContainer'); if (portalContainer && portalContainer.children.length > 0) { return; } setOpen(true); } }, [opened, setOpen] ) ); return opened && setOpen(false)} />; }