diff --git a/src/app/components/SpaceChildDirectsProvider.tsx b/src/app/components/SpaceChildDirectsProvider.tsx new file mode 100644 index 00000000..43fd216a --- /dev/null +++ b/src/app/components/SpaceChildDirectsProvider.tsx @@ -0,0 +1,24 @@ +import { ReactNode } from 'react'; +import { RoomToParents } from '../../types/matrix/room'; +import { useMatrixClient } from '../hooks/useMatrixClient'; +import { allRoomsAtom } from '../state/room-list/roomList'; +import { useSpaceChildDirects } from '../state/hooks/roomList'; + +type SpaceChildDirectsProviderProps = { + spaceId: string; + mDirects: Set; + roomToParents: RoomToParents; + children: (rooms: string[]) => ReactNode; +}; +export function SpaceChildDirectsProvider({ + spaceId, + roomToParents, + mDirects, + children, +}: SpaceChildDirectsProviderProps) { + const mx = useMatrixClient(); + + const childDirects = useSpaceChildDirects(mx, spaceId, allRoomsAtom, mDirects, roomToParents); + + return children(childDirects); +} diff --git a/src/app/components/SpaceChildRoomsProvider.tsx b/src/app/components/SpaceChildRoomsProvider.tsx index 4bbc7d6d..7defba0e 100644 --- a/src/app/components/SpaceChildRoomsProvider.tsx +++ b/src/app/components/SpaceChildRoomsProvider.tsx @@ -6,17 +6,19 @@ import { useSpaceChildRooms } from '../state/hooks/roomList'; type SpaceChildRoomsProviderProps = { spaceId: string; + mDirects: Set; roomToParents: RoomToParents; children: (rooms: string[]) => ReactNode; }; export function SpaceChildRoomsProvider({ spaceId, roomToParents, + mDirects, children, }: SpaceChildRoomsProviderProps) { const mx = useMatrixClient(); - const childRooms = useSpaceChildRooms(mx, spaceId, allRoomsAtom, roomToParents); + const childRooms = useSpaceChildRooms(mx, spaceId, allRoomsAtom, mDirects, roomToParents); return children(childRooms); } diff --git a/src/app/pages/App.tsx b/src/app/pages/App.tsx index 245c28d8..3093c1b5 100644 --- a/src/app/pages/App.tsx +++ b/src/app/pages/App.tsx @@ -42,7 +42,7 @@ import { ClientLayout, ClientRoot } from './client'; import { Home, HomeSearch } from './client/home'; import { RoomViewer } from '../organisms/room/Room'; import { Direct } from './client/direct'; -import { SpaceViewer } from './client/space'; +import { RouteSpaceProvider, Space, SpaceSearch } from './client/space'; import { Explore, ExploreRedirect, FeaturedRooms, PublicRooms } from './client/explore'; import { Notifications, Inbox, InboxRedirect, Invites } from './client/inbox'; import { setAfterLoginRedirectPath } from './afterLoginRedirectPath'; @@ -94,11 +94,13 @@ const createRouter = (clientConfig: ClientConfig) => { create

} /> } /> - }> - welcome

} /> - lobby

} /> - search

} /> - } /> + }> + }> + welcome

} /> + lobby

} /> + } /> + } /> + }> } /> diff --git a/src/app/pages/client/space/Search.tsx b/src/app/pages/client/space/Search.tsx new file mode 100644 index 00000000..eea61850 --- /dev/null +++ b/src/app/pages/client/space/Search.tsx @@ -0,0 +1,36 @@ +import React, { useRef } from 'react'; +import { Box, Icon, Icons, Text, Scroll } from 'folds'; +import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page'; +import { MessageSearch } from '../../../features/message-search'; + +export function SpaceSearch() { + const scrollRef = useRef(null); + const rooms = ['']; + + return ( + + + + + + Message Search + + + + + + + + + + + + + + ); +} diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index 5c99f40f..adb2c328 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -1,20 +1,16 @@ import React, { useRef } from 'react'; -import { Outlet, useParams } from 'react-router-dom'; +import { Outlet } from 'react-router-dom'; import { useAtomValue } from 'jotai'; import { Avatar, Box, Icon, Icons, Text } from 'folds'; -import { Room } from 'matrix-js-sdk'; import { ClientContentLayout } from '../ClientContentLayout'; import { ClientDrawerLayout } from '../ClientDrawerLayout'; import { ClientDrawerHeaderLayout } from '../ClientDrawerHeaderLayout'; -import { - useSpaceRecursiveChildDirects, - useSpaceRecursiveChildSpaces, -} from '../../../state/hooks/roomList'; +import { useSpaceChildSpacesRecursive } from '../../../state/hooks/roomList'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { allRoomsAtom } from '../../../state/room-list/roomList'; import { mDirectAtom } from '../../../state/mDirectList'; import { roomToParentsAtom } from '../../../state/room/roomToParents'; -import { factoryRoomIdByAtoZ } from '../../../utils/sort'; +import { factoryRoomIdByActivity, factoryRoomIdByAtoZ } from '../../../utils/sort'; import { ClientDrawerContentLayout } from '../ClientDrawerContentLayout'; import { NavCategory, @@ -24,43 +20,38 @@ import { NavLink, } from '../../../components/nav'; import { UnreadBadge, UnreadBadgeCenter } from '../../../components/unread-badge'; -import { RoomIcon } from '../../../components/room-avatar'; +import { RoomAvatar, RoomIcon } from '../../../components/room-avatar'; import { getSpaceLobbyPath, getSpaceRoomPath, getSpaceSearchPath } from '../../pathUtils'; import { getCanonicalAliasOrRoomId } from '../../../utils/matrix'; import { RoomUnreadProvider } from '../../../components/RoomUnreadProvider'; import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom'; import { - useSelectedSpace, useSpaceLobbySelected, useSpaceSearchSelected, } from '../../../hooks/router/useSelectedSpace'; import { SpaceChildRoomsProvider } from '../../../components/SpaceChildRoomsProvider'; +import { getRoomAvatarUrl } from '../../../utils/room'; +import { nameInitials } from '../../../utils/common'; +import { SpaceChildDirectsProvider } from '../../../components/SpaceChildDirectsProvider'; +import { useSpace } from '../../../hooks/useSpace'; -export function Space({ spaceIdOrAlias, space }: { spaceIdOrAlias: string; space: Room }) { +export function Space() { const mx = useMatrixClient(); + const space = useSpace(); + const spaceIdOrAlias = getCanonicalAliasOrRoomId(mx, space.roomId); const scrollRef = useRef(null); const mDirects = useAtomValue(mDirectAtom); const roomToParents = useAtomValue(roomToParentsAtom); - const childSpaces = useSpaceRecursiveChildSpaces(mx, space.roomId, allRoomsAtom, roomToParents); - const childDirects = useSpaceRecursiveChildDirects( - mx, - space.roomId, - allRoomsAtom, - mDirects, - roomToParents - ); + const childSpaces = useSpaceChildSpacesRecursive(mx, space.roomId, allRoomsAtom, roomToParents); const selectedRoomId = useSelectedRoom(); const lobbySelected = useSpaceLobbySelected(spaceIdOrAlias); const searchSelected = useSpaceSearchSelected(spaceIdOrAlias); const getToLink = (roomId: string) => - getSpaceRoomPath( - getCanonicalAliasOrRoomId(mx, space.roomId), - getCanonicalAliasOrRoomId(mx, roomId) - ); + getSpaceRoomPath(spaceIdOrAlias, getCanonicalAliasOrRoomId(mx, roomId)); const renderRoomSelector = (roomId: string) => { const room = mx.getRoom(roomId); @@ -81,7 +72,16 @@ export function Space({ spaceIdOrAlias, space }: { spaceIdOrAlias: string; space - + {mDirects.has(roomId) ? ( + {nameInitials(room.name)}} + /> + ) : ( + + )} @@ -151,7 +151,11 @@ export function Space({ spaceIdOrAlias, space }: { spaceIdOrAlias: string; space - + {(childRooms) => childRooms.length > 0 && ( @@ -167,30 +171,52 @@ export function Space({ spaceIdOrAlias, space }: { spaceIdOrAlias: string; space - {(childRooms) => - childRooms.length > 0 && ( - - - {mx.getRoom(childSpaceId)?.name} - - {Array.from(childRooms) - .sort(factoryRoomIdByAtoZ(mx)) - .map(renderRoomSelector)} - - ) - } + {(childRooms) => ( + + {(childDirects) => + (childRooms.length > 0 || childDirects.length > 0) && ( + + + {mx.getRoom(childSpaceId)?.name} + + {Array.from(childRooms) + .sort(factoryRoomIdByAtoZ(mx)) + .map(renderRoomSelector)} + {Array.from(childDirects) + .sort(factoryRoomIdByActivity(mx)) + .map(renderRoomSelector)} + + ) + } + + )} ))} - {childDirects.length > 0 && ( - - - People - - {Array.from(childDirects).sort(factoryRoomIdByAtoZ(mx)).map(renderRoomSelector)} - - )} + + {(childDirects) => + childDirects.length > 0 && ( + + + People + + {Array.from(childDirects) + .sort(factoryRoomIdByActivity(mx)) + .map(renderRoomSelector)} + + ) + } + @@ -200,17 +226,3 @@ export function Space({ spaceIdOrAlias, space }: { spaceIdOrAlias: string; space ); } - -export function SpaceViewer() { - const mx = useMatrixClient(); - - const { spaceIdOrAlias } = useParams(); - const selectedSpaceId = useSelectedSpace(); - const space = mx.getRoom(selectedSpaceId); - - if (!space || !spaceIdOrAlias) { - return

TODO: join space screen

; - } - - return ; -} diff --git a/src/app/pages/client/space/SpaceProvider.tsx b/src/app/pages/client/space/SpaceProvider.tsx new file mode 100644 index 00000000..29a8fa0f --- /dev/null +++ b/src/app/pages/client/space/SpaceProvider.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Outlet } from 'react-router-dom'; +import { useMatrixClient } from '../../../hooks/useMatrixClient'; +import { useSpaces } from '../../../state/hooks/roomList'; +import { allRoomsAtom } from '../../../state/room-list/roomList'; +import { useSelectedSpace } from '../../../hooks/router/useSelectedSpace'; +import { SpaceProvider } from '../../../hooks/useSpace'; + +export function RouteSpaceProvider() { + const mx = useMatrixClient(); + const joinedSpaces = useSpaces(mx, allRoomsAtom); + + const selectedSpaceId = useSelectedSpace(); + const space = mx.getRoom(selectedSpaceId); + + if (!space || !joinedSpaces.includes(space.roomId)) { + return

TODO: join space screen

; + } + + return ( + + + + ); +} diff --git a/src/app/pages/client/space/index.ts b/src/app/pages/client/space/index.ts index b0dd6742..57afadc4 100644 --- a/src/app/pages/client/space/index.ts +++ b/src/app/pages/client/space/index.ts @@ -1 +1,3 @@ +export * from './SpaceProvider'; export * from './Space'; +export * from './Search'; diff --git a/src/app/state/hooks/roomList.ts b/src/app/state/hooks/roomList.ts index d6a026b9..7a8fde8a 100644 --- a/src/app/state/hooks/roomList.ts +++ b/src/app/state/hooks/roomList.ts @@ -7,12 +7,6 @@ import { compareRoomsEqual } from '../room-list/utils'; import { allRoomsAtom } from '../room-list/roomList'; import { RoomToParents } from '../../../types/matrix/room'; -/** - * select list of space room id's from all rooms - * @param mx to check room type - * @param roomsAtom to pick rooms - * @returns list of space id's - */ export const useSpaces = (mx: MatrixClient, roomsAtom: typeof allRoomsAtom) => { const selector = useCallback( (rooms: string[]) => rooms.filter((roomId) => isSpace(mx.getRoom(roomId))), @@ -21,13 +15,6 @@ export const useSpaces = (mx: MatrixClient, roomsAtom: typeof allRoomsAtom) => { return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of space room ids from all rooms which doesn't have any parent - * @param mx to check room type - * @param roomsAtom to pick rooms - * @param roomToParents: to exclude space's with parent - * @returns list of space ids - */ export const useOrphanSpaces = ( mx: MatrixClient, roomsAtom: typeof allRoomsAtom, @@ -41,15 +28,7 @@ export const useOrphanSpaces = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of all room ids from all rooms for which spaceId is in all parents - * @param mx to check room type - * @param spaceId as root parent - * @param roomsAtom to pick rooms - * @param roomToParents: to include child room - * @returns list of space ids - */ -export const useSpaceRecursiveChildSpaces = ( +export const useSpaceChildSpacesRecursive = ( mx: MatrixClient, spaceId: string, roomsAtom: typeof allRoomsAtom, @@ -68,40 +47,27 @@ export const useSpaceRecursiveChildSpaces = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of all room ids from all rooms for which spaceId is in parents - * @param mx to check room type - * @param spaceId as root parent - * @param roomsAtom to pick rooms - * @param roomToParents: to include child room - * @returns list of space ids - */ export const useSpaceChildRooms = ( mx: MatrixClient, spaceId: string, roomsAtom: typeof allRoomsAtom, + mDirects: Set, roomToParents: RoomToParents ) => { const selector = useCallback( (rooms: string[]) => rooms.filter( - (roomId) => isRoom(mx.getRoom(roomId)) && roomToParents.get(roomId)?.has(spaceId) + (roomId) => + isRoom(mx.getRoom(roomId)) && + !mDirects.has(roomId) && + roomToParents.get(roomId)?.has(spaceId) ), - [mx, spaceId, roomToParents] + [mx, spaceId, mDirects, roomToParents] ); return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of all room ids from all rooms for which spaceId is in all parents - * @param mx to check room type - * @param spaceId as root parent - * @param roomsAtom to pick rooms - * @param mDirects to include only direct rooms - * @param roomToParents: to include child room - * @returns list of direct room ids - */ -export const useSpaceRecursiveChildDirects = ( +export const useSpaceChildDirectsRecursive = ( mx: MatrixClient, spaceId: string, roomsAtom: typeof allRoomsAtom, @@ -122,15 +88,6 @@ export const useSpaceRecursiveChildDirects = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of all room ids from all rooms for which spaceId is in parents and is in mDirects - * @param mx to check room type - * @param spaceId as root parent - * @param roomsAtom to pick rooms - * @param mDirects to include only direct rooms - * @param roomToParents: to include child rooms - * @returns list of space ids - */ export const useSpaceChildDirects = ( mx: MatrixClient, spaceId: string, @@ -151,13 +108,6 @@ export const useSpaceChildDirects = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of room ids from all rooms which are not direct(dm) - * @param mx to check room type - * @param roomsAtom to pick rooms - * @param mDirects to exclude direct rooms - * @returns list of room ids - */ export const useRooms = ( mx: MatrixClient, roomsAtom: typeof allRoomsAtom, @@ -171,14 +121,6 @@ export const useRooms = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of room ids from all rooms which are not direct(dm) and doesn't have any parent - * @param mx to check room type - * @param roomsAtom to pick rooms - * @param mDirects to exclude direct rooms - * @param roomToParents to exclude rooms with parent - * @returns list of room ids - */ export const useOrphanRooms = ( mx: MatrixClient, roomsAtom: typeof allRoomsAtom, @@ -196,13 +138,6 @@ export const useOrphanRooms = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of room ids from all rooms which are direct(dm) - * @param mx to check room type - * @param roomsAtom to pick rooms - * @param mDirects to only include direct rooms - * @returns list of room ids - */ export const useDirects = ( mx: MatrixClient, roomsAtom: typeof allRoomsAtom, @@ -216,12 +151,6 @@ export const useDirects = ( return useAtomValue(selectAtom(roomsAtom, selector, compareRoomsEqual)); }; -/** - * select list of room ids for which room type is unsupported - * @param mx to check room type - * @param roomsAtom to pick rooms - * @returns list of unsupported room ids - */ export const useUnsupportedRooms = (mx: MatrixClient, roomsAtom: typeof allRoomsAtom) => { const selector = useCallback( (rooms: string[]) => rooms.filter((roomId) => isUnsupportedRoom(mx.getRoom(roomId))),