From 3ee95a295d82a4339920b4b9ea74cbb3baa19755 Mon Sep 17 00:00:00 2001 From: Max Litruv Boonzaayer Date: Mon, 6 Jul 2026 15:35:21 +1000 Subject: [PATCH] feat: Implement forum feed layout and refactor space navigation logic to support new routing structure --- .../features/forum/ForumAwareSpaceLayout.tsx | 30 +++++- src/app/features/forum/ForumFeedPage.tsx | 6 ++ src/app/features/forum/ForumSpaceLayout.tsx | 32 +------ src/app/features/forum/index.ts | 1 + src/app/features/lobby/Lobby.tsx | 11 +-- src/app/features/lobby/LobbyHeader.tsx | 25 ++++- src/app/features/space/SpaceOptionsMenu.tsx | 41 ++++++++ src/app/hooks/router/useSelectedSpace.ts | 31 +++--- src/app/hooks/useAutoJoinSpaceRooms.ts | 95 ++++++++++++++----- src/app/pages/Router.tsx | 25 ++--- src/app/pages/client/sidebar/SpaceTabs.tsx | 6 +- src/app/pages/client/space/Space.tsx | 77 ++++++++------- .../pages/client/space/SpaceIndexRedirect.tsx | 26 +++++ src/app/pages/client/space/SpaceProvider.tsx | 3 + src/app/pages/client/space/index.ts | 1 + src/app/pages/pathUtils.ts | 19 ++++ src/app/pages/paths.ts | 2 + 17 files changed, 296 insertions(+), 135 deletions(-) create mode 100644 src/app/features/forum/ForumFeedPage.tsx create mode 100644 src/app/pages/client/space/SpaceIndexRedirect.tsx diff --git a/src/app/features/forum/ForumAwareSpaceLayout.tsx b/src/app/features/forum/ForumAwareSpaceLayout.tsx index 8dfa98c..30750a9 100644 --- a/src/app/features/forum/ForumAwareSpaceLayout.tsx +++ b/src/app/features/forum/ForumAwareSpaceLayout.tsx @@ -1,15 +1,31 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { PageRoot } from '../../components/page'; import { AnimatedOutlet } from '../../components/AnimatedOutlet'; import { MobileFriendlyPageNav } from '../../pages/MobileFriendly'; import { SPACE_PATH } from '../../pages/paths'; import { Space } from '../../pages/client/space/Space'; +import { useMatrixClient } from '../../hooks/useMatrixClient'; +import { useSelectedRoom } from '../../hooks/router/useSelectedRoom'; +import { useSpace } from '../../hooks/useSpace'; +import { isForumContainer, shouldShowForumLobby } from '../../utils/room'; +import { ForumBoardProvider } from './ForumBoardContext'; /** * Space sidebar + outlet. Forum spaces render ForumFeedSidebar in Space.tsx. */ export function ForumAwareSpaceLayout() { - return ( + const mx = useMatrixClient(); + const space = useSpace(); + const selectedRoomId = useSelectedRoom(); + + const scope = useMemo(() => { + const room = selectedRoomId ? mx.getRoom(selectedRoomId) : null; + const topicRoomId = + room && room.roomId !== space.roomId && !isForumContainer(room) ? room.roomId : undefined; + return { forumSpaceId: space.roomId, topicRoomId }; + }, [mx, selectedRoomId, space.roomId]); + + const layout = ( @@ -20,4 +36,14 @@ export function ForumAwareSpaceLayout() { ); + + if (!shouldShowForumLobby(space)) { + return layout; + } + + return ( + + {layout} + + ); } diff --git a/src/app/features/forum/ForumFeedPage.tsx b/src/app/features/forum/ForumFeedPage.tsx new file mode 100644 index 0000000..c36a371 --- /dev/null +++ b/src/app/features/forum/ForumFeedPage.tsx @@ -0,0 +1,6 @@ +import { ForumBoardDetail } from './ForumBoardDetail'; + +/** Forum post feed in the main pane (sidebar holds filters + post list). */ +export function ForumFeedPage() { + return ; +} diff --git a/src/app/features/forum/ForumSpaceLayout.tsx b/src/app/features/forum/ForumSpaceLayout.tsx index fe3ee78..538e267 100644 --- a/src/app/features/forum/ForumSpaceLayout.tsx +++ b/src/app/features/forum/ForumSpaceLayout.tsx @@ -1,30 +1,8 @@ -import React, { ReactNode, useMemo } from 'react'; -import { useMatrixClient } from '../../hooks/useMatrixClient'; -import { useSelectedRoom } from '../../hooks/router/useSelectedRoom'; -import { useSpace } from '../../hooks/useSpace'; -import { isForumContainer, shouldShowForumLobby } from '../../utils/room'; -import { ForumBoardProvider } from './ForumBoardContext'; +import React, { ReactNode } from 'react'; -/** Shares forum board state between space sidebar and lobby/room outlet. */ +/** + * @deprecated Forum board context now lives in ForumAwareSpaceLayout. + */ export function ForumSpaceLayout({ children }: { children: ReactNode }) { - const mx = useMatrixClient(); - const space = useSpace(); - const selectedRoomId = useSelectedRoom(); - - const scope = useMemo(() => { - const room = selectedRoomId ? mx.getRoom(selectedRoomId) : null; - const topicRoomId = - room && room.roomId !== space.roomId && !isForumContainer(room) ? room.roomId : undefined; - return { forumSpaceId: space.roomId, topicRoomId }; - }, [mx, selectedRoomId, space.roomId]); - - if (!shouldShowForumLobby(space)) { - return children; - } - - return ( - - {children} - - ); + return children; } diff --git a/src/app/features/forum/index.ts b/src/app/features/forum/index.ts index 304cadb..e6d69c1 100644 --- a/src/app/features/forum/index.ts +++ b/src/app/features/forum/index.ts @@ -3,6 +3,7 @@ export { ForumBoardDetail } from './ForumBoardDetail'; export { ForumSortIcons } from './forumLucideIcons'; export { ForumSpaceShell } from './ForumSpaceShell'; export { ForumThreadDetail } from './ForumThreadDetail'; +export { ForumFeedPage } from './ForumFeedPage'; export { ForumAwareSpaceLayout } from './ForumAwareSpaceLayout'; export { ForumSpaceLayout } from './ForumSpaceLayout'; export type { ForumBoardScope } from './useForumBoard'; diff --git a/src/app/features/lobby/Lobby.tsx b/src/app/features/lobby/Lobby.tsx index 9c26484..2207888 100644 --- a/src/app/features/lobby/Lobby.tsx +++ b/src/app/features/lobby/Lobby.tsx @@ -41,8 +41,7 @@ import { getSpaceRoomPath } from '../../pages/pathUtils'; import { StateEvent } from '../../../types/matrix/room'; import { CanDropCallback, useDnDMonitor } from './DnD'; import { ASCIILexicalTable, orderKeys } from '../../utils/ASCIILexicalTable'; -import { getStateEvent, shouldShowForumLobby } from '../../utils/room'; -import { ForumBoardDetail } from '../forum/ForumBoardDetail'; +import { getStateEvent } from '../../utils/room'; import { useClosedLobbyCategoriesAtom } from '../../state/hooks/closedLobbyCategories'; import { makeCinnySpacesContent, @@ -151,15 +150,7 @@ const useCanDropLobbyItem = ( return canDrop; }; -function ForumSpaceLobby() { - return ; -} - export function Lobby() { - const space = useSpace(); - if (shouldShowForumLobby(space)) { - return ; - } return ; } diff --git a/src/app/features/lobby/LobbyHeader.tsx b/src/app/features/lobby/LobbyHeader.tsx index 0a8540d..6bec403 100644 --- a/src/app/features/lobby/LobbyHeader.tsx +++ b/src/app/features/lobby/LobbyHeader.tsx @@ -27,8 +27,12 @@ import { AddExistingModal } from '../add-existing'; import { SpeechBubble } from '../../components/speech-bubble/SpeechBubble'; import { SpaceOptionsMenu, type OpenAddExistingOptions } from '../space/SpaceOptionsMenu'; import type { HierarchyItemSpace } from '../../hooks/useSpaceHierarchy'; -import { StateEvent } from '../../../types/matrix/room'; +import { useNavigate } from 'react-router-dom'; +import { getCanonicalAliasOrRoomId } from '../../utils/matrix'; +import { getSpaceFeedPath } from '../../pages/pathUtils'; +import { shouldShowForumLobby } from '../../utils/room'; import { useForumBoardContextOptionally } from '../forum/ForumBoardContext'; +import { StateEvent } from '../../../types/matrix/room'; type LobbyMenuProps = { powerLevels: IPowerLevels; @@ -37,7 +41,9 @@ type LobbyMenuProps = { const LobbyMenu = forwardRef( ({ powerLevels, requestClose }, ref) => { const mx = useMatrixClient(); + const navigate = useNavigate(); const space = useSpace(); + const isForum = shouldShowForumLobby(space); const creators = useRoomCreators(space); const permissions = useRoomPermissions(creators, powerLevels); @@ -55,6 +61,11 @@ const LobbyMenu = forwardRef( requestClose(); }; + const handleOpenFeed = () => { + navigate(getSpaceFeedPath(getCanonicalAliasOrRoomId(mx, space.roomId))); + requestClose(); + }; + return ( {invitePrompt && ( @@ -67,6 +78,18 @@ const LobbyMenu = forwardRef( /> )} + {isForum && ( + } + radii="300" + > + + Feed + + + )} ( ({ room, requestClose, forumAdd, onOpenAddExisting }, ref) => { const mx = useMatrixClient(); + const navigate = useNavigate(); + const onFeed = useSpaceFeedSelected(); + const isForum = shouldShowForumLobby(room); const [hideActivity] = useSetting(settingsAtom, 'hideActivity'); const [developerTools] = useSetting(settingsAtom, 'developerTools'); const roomToParents = useAtomValue(roomToParentsAtom); @@ -101,6 +108,16 @@ export const SpaceOptionsMenu = forwardRef { + navigate(getSpaceFeedPath(getCanonicalAliasOrRoomId(mx, room.roomId))); + requestClose(); + }; + + const handleOpenManage = () => { + navigate(getSpaceLobbyPath(getCanonicalAliasOrRoomId(mx, room.roomId))); + requestClose(); + }; + const handleAddTopic = () => { if (!forumAdd) return; openCreateRoomModal(forumAdd.item.roomId); @@ -200,6 +217,30 @@ export const SpaceOptionsMenu = forwardRef )} + {isForum && !onFeed && ( + } + radii="300" + > + + Feed + + + )} + {isForum && onFeed && ( + } + radii="300" + > + + Manage + + + )} { const mx = useMatrixClient(); @@ -16,22 +15,18 @@ export const useSelectedSpace = (): string | undefined => { return spaceId; }; -export const useSpaceLobbySelected = (spaceIdOrAlias: string): boolean => { - const match = useMatch({ - path: getSpaceLobbyPath(spaceIdOrAlias), - caseSensitive: true, - end: false, - }); - - return !!match; +/** True when the current URL is the forum feed route. */ +export const useSpaceFeedSelected = (): boolean => { + const { pathname } = useLocation(); + return /\/feed\/?$/.test(pathname); }; -export const useSpaceSearchSelected = (spaceIdOrAlias: string): boolean => { - const match = useMatch({ - path: getSpaceSearchPath(spaceIdOrAlias), - caseSensitive: true, - end: false, - }); - - return !!match; +export const useSpaceLobbySelected = (_spaceIdOrAlias?: string): boolean => { + const { pathname } = useLocation(); + return /\/lobby\/?$/.test(pathname); +}; + +export const useSpaceSearchSelected = (_spaceIdOrAlias?: string): boolean => { + const { pathname } = useLocation(); + return /\/search\/?$/.test(pathname); }; diff --git a/src/app/hooks/useAutoJoinSpaceRooms.ts b/src/app/hooks/useAutoJoinSpaceRooms.ts index b29d712..6cc9023 100644 --- a/src/app/hooks/useAutoJoinSpaceRooms.ts +++ b/src/app/hooks/useAutoJoinSpaceRooms.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef, useCallback } from 'react'; +import { useEffect, useCallback } from 'react'; import { MatrixClient, Room, RoomEvent } from 'matrix-js-sdk'; import { IHierarchyRoom } from 'matrix-js-sdk/lib/@types/spaces'; import { useAtomValue, useSetAtom } from 'jotai'; @@ -10,6 +10,7 @@ import { RoomNotificationMode, } from './useRoomsNotificationPreferences'; import { updateJoiningProgressAtom } from '../state/joiningProgress'; +import { useMatrixClient } from './useMatrixClient'; const PER_PAGE_COUNT = 100; const MAX_PAGES = 50; @@ -18,6 +19,8 @@ const JOIN_DELAY_MS = 500; /** Join rules that allow automatic joining */ const AUTO_JOINABLE_RULES = ['public', 'restricted', 'knock_restricted']; +const processingSpaces = new Set(); + /** * Extracts the server name from a Matrix room ID * @param roomId - The room ID (e.g., "!abc123:matrix.org") @@ -46,12 +49,12 @@ function canAutoJoin(hierarchyRoom: IHierarchyRoom): boolean { } /** - * Checks if a hierarchy item is a space + * Checks if a hierarchy item is a space (including m.forum category spaces) * @param hierarchyRoom - The room info from the space hierarchy * @returns Whether the item is a space */ function isHierarchySpace(hierarchyRoom: IHierarchyRoom): boolean { - return hierarchyRoom.room_type === 'm.space'; + return hierarchyRoom.room_type === 'm.space' || hierarchyRoom.room_type === 'm.forum'; } /** @@ -177,6 +180,29 @@ async function joinRoomsSequentially( ); } +/** + * Joins all auto-joinable children of a space (and nested spaces/rooms). + */ +export async function autoJoinSpaceChildren( + mx: MatrixClient, + spaceId: string, + onProgress?: ProgressCallback +): Promise { + if (processingSpaces.has(spaceId)) { + return; + } + + processingSpaces.add(spaceId); + + try { + const hierarchyRooms = await fetchSpaceHierarchy(mx, spaceId); + const childRooms = hierarchyRooms.filter((r) => r.room_id !== spaceId); + await joinRoomsSequentially(mx, childRooms, spaceId, onProgress); + } finally { + processingSpaces.delete(spaceId); + } +} + /** * Hook that automatically joins all accessible rooms when joining a space * @param mx - Matrix client instance @@ -184,7 +210,6 @@ async function joinRoomsSequentially( export function useAutoJoinSpaceRooms(mx: MatrixClient): void { const settings = useAtomValue(settingsAtom); const setJoiningProgress = useSetAtom(updateJoiningProgressAtom); - const processingSpaces = useRef>(new Set()); const handleSpaceJoin = useCallback( async (room: Room) => { @@ -192,7 +217,7 @@ export function useAutoJoinSpaceRooms(mx: MatrixClient): void { return; } - // Only process spaces + // Only process spaces (includes m.forum containers) if (!isSpace(room)) { return; } @@ -204,27 +229,11 @@ export function useAutoJoinSpaceRooms(mx: MatrixClient): void { const spaceId = room.roomId; - // Prevent duplicate processing - if (processingSpaces.current.has(spaceId)) { - return; - } - - processingSpaces.current.add(spaceId); - try { - // Fetch the space hierarchy - const hierarchyRooms = await fetchSpaceHierarchy(mx, spaceId); - - // Filter out the space itself - const childRooms = hierarchyRooms.filter((r) => r.room_id !== spaceId); - - // Join all accessible rooms with progress tracking - await joinRoomsSequentially(mx, childRooms, spaceId, (current, total) => { + await autoJoinSpaceChildren(mx, spaceId, (current, total) => { setJoiningProgress({ spaceId, progress: { current, total } }); }); } finally { - processingSpaces.current.delete(spaceId); - // Clear progress when done setJoiningProgress({ spaceId, progress: null }); } }, @@ -245,3 +254,45 @@ export function useAutoJoinSpaceRooms(mx: MatrixClient): void { }; }, [mx, handleSpaceJoin]); } + +/** + * Auto-joins space children when visiting an already-joined space (e.g. forum spaces). + */ +export function useAutoJoinOnSpaceVisit(space: Room | undefined): void { + const mx = useMatrixClient(); + const settings = useAtomValue(settingsAtom); + const setJoiningProgress = useSetAtom(updateJoiningProgressAtom); + + useEffect(() => { + if (!space || !settings.autoJoinSpaceRooms) { + return; + } + if (!isSpace(space)) { + return; + } + if (space.getMyMembership() !== Membership.Join) { + return; + } + + const spaceId = space.roomId; + let cancelled = false; + + void (async () => { + try { + await autoJoinSpaceChildren(mx, spaceId, (current, total) => { + if (!cancelled) { + setJoiningProgress({ spaceId, progress: { current, total } }); + } + }); + } finally { + if (!cancelled) { + setJoiningProgress({ spaceId, progress: null }); + } + } + })(); + + return () => { + cancelled = true; + }; + }, [space, settings.autoJoinSpaceRooms, mx, setJoiningProgress]); +} \ No newline at end of file diff --git a/src/app/pages/Router.tsx b/src/app/pages/Router.tsx index 260980b..3cc7ab4 100644 --- a/src/app/pages/Router.tsx +++ b/src/app/pages/Router.tsx @@ -23,6 +23,7 @@ import { _FEATURED_PATH, _INVITES_PATH, _JOIN_PATH, + _FEED_PATH, _LOBBY_PATH, _NOTIFICATIONS_PATH, _ROOM_PATH, @@ -37,14 +38,13 @@ import { getInboxNotificationsPath, getLoginPath, getOriginBaseUrl, - getSpaceLobbyPath, } from './pathUtils'; import { ClientBindAtoms, ClientLayout, ClientRoot } from './client'; import { Home, HomeRouteRoomProvider, HomeSearch } from './client/home'; import { Direct, DirectCreate, DirectRouteRoomProvider } from './client/direct'; -import { RouteSpaceProvider, Space, SpaceRouteRoomProvider, SpaceSearch } from './client/space'; +import { RouteSpaceProvider, SpaceRouteRoomProvider, SpaceSearch, SpaceIndexRedirect } from './client/space'; import { ForumAwareSpaceLayout } from '../features/forum/ForumAwareSpaceLayout'; -import { ForumSpaceLayout } from '../features/forum/ForumSpaceLayout'; +import { ForumFeedPage } from '../features/forum/ForumFeedPage'; import { Explore, FeaturedRooms, PublicRooms } from './client/explore'; import { Notifications, Inbox, Invites } from './client/inbox'; import { setAfterLoginRedirectPath } from './afterLoginRedirectPath'; @@ -238,25 +238,12 @@ export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize) path={SPACE_PATH} element={ - - - + } > - {mobile ? null : ( - { - const { spaceIdOrAlias } = params; - if (spaceIdOrAlias) { - return redirect(getSpaceLobbyPath(spaceIdOrAlias)); - } - return null; - }} - element={} - /> - )} + } /> + } /> } /> } /> = (evt) => { @@ -1206,7 +1206,7 @@ export function HiddenSpacesTabs() { return; } - navigate(getSpaceLobbyPath(getCanonicalAliasOrRoomId(mx, targetSpaceId))); + navigate(getSpaceDefaultPath(mx, targetSpaceId)); }; const handleHomeClick = () => { diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index 1a86b1d..193c16c 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -335,7 +335,12 @@ export function Space() { const getToLink = (roomId: string) => getSpaceRoomPath(spaceIdOrAlias, getCanonicalAliasOrRoomId(mx, roomId)); - if (shouldShowForumLobby(space)) { + const isForum = shouldShowForumLobby(space); + // Forum feed unless user opened manage, search, or a room (not tied to URL alias encoding). + const feedActive = isForum && !lobbySelected && !searchSelected && !selectedRoomId; + const showForumFeedSidebar = feedActive; + + if (showForumFeedSidebar) { return ( @@ -346,6 +351,8 @@ export function Space() { ); } + const spacePath = getCanonicalAliasOrRoomId(mx, space.roomId); + return ( @@ -358,38 +365,42 @@ export function Space() { /> )} - - - - - - - - - - Lobby - - - - - - - - - - - - - - - - Message Search - - - - - - + {!isForum && ( + <> + + + + + + + + + + Lobby + + + + + + + + + + + + + + + + Message Search + + + + + + + + )} { + navigate(getSpaceDefaultPath(mx, space.roomId), { replace: true }); + }, [mx, navigate, space.roomId]); + + // Avoid a blank main pane while redirecting forum spaces to /feed/. + if (isForum) { + return ; + } + + return null; +} diff --git a/src/app/pages/client/space/SpaceProvider.tsx b/src/app/pages/client/space/SpaceProvider.tsx index 2e0f79a..2fa6f76 100644 --- a/src/app/pages/client/space/SpaceProvider.tsx +++ b/src/app/pages/client/space/SpaceProvider.tsx @@ -1,6 +1,7 @@ import React, { ReactNode } from 'react'; import { useParams } from 'react-router-dom'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; +import { useAutoJoinOnSpaceVisit } from '../../../hooks/useAutoJoinSpaceRooms'; import { useSpaces } from '../../../state/hooks/roomList'; import { allRoomsAtom } from '../../../state/room-list/roomList'; import { useSelectedSpace } from '../../../hooks/router/useSelectedSpace'; @@ -21,6 +22,8 @@ export function RouteSpaceProvider({ children }: RouteSpaceProviderProps) { const selectedSpaceId = useSelectedSpace(); const space = mx.getRoom(selectedSpaceId); + useAutoJoinOnSpaceVisit(space ?? undefined); + if (!space || !joinedSpaces.includes(space.roomId)) { return ; } diff --git a/src/app/pages/client/space/index.ts b/src/app/pages/client/space/index.ts index 0e32d93..686dc7b 100644 --- a/src/app/pages/client/space/index.ts +++ b/src/app/pages/client/space/index.ts @@ -1,3 +1,4 @@ +export * from './SpaceIndexRedirect'; export * from './SpaceProvider'; export * from './Space'; export * from './Search'; diff --git a/src/app/pages/pathUtils.ts b/src/app/pages/pathUtils.ts index 9ce7e8e..b1ccfac 100644 --- a/src/app/pages/pathUtils.ts +++ b/src/app/pages/pathUtils.ts @@ -20,6 +20,7 @@ import { REGISTER_PATH, RESET_PASSWORD_PATH, ROOT_PATH, + SPACE_FEED_PATH, SPACE_LOBBY_PATH, SPACE_PATH, SPACE_ROOM_PATH, @@ -28,6 +29,9 @@ import { } from './paths'; import { trimLeadingSlash, trimTrailingSlash } from '../utils/common'; import { HashRouterConfig } from '../hooks/useClientConfig'; +import type { MatrixClient } from 'matrix-js-sdk'; +import { getCanonicalAliasOrRoomId } from '../utils/matrix'; +import { shouldShowForumLobby } from '../utils/room'; export const joinPathComponent = (path: Path): string => path.pathname + path.search + path.hash; @@ -128,6 +132,21 @@ export const getSpaceLobbyPath = (spaceIdOrAlias: string): string => { }; return generatePath(SPACE_LOBBY_PATH, params); }; +export const getSpaceFeedPath = (spaceIdOrAlias: string): string => { + const params = { + spaceIdOrAlias: encodeURIComponent(spaceIdOrAlias), + }; + return generatePath(SPACE_FEED_PATH, params); +}; +/** Forum spaces open the post feed; other spaces open the lobby. */ +export const getSpaceDefaultPath = (mx: MatrixClient, spaceId: string): string => { + const spaceIdOrAlias = getCanonicalAliasOrRoomId(mx, spaceId); + const space = mx.getRoom(spaceId); + if (space && shouldShowForumLobby(space)) { + return getSpaceFeedPath(spaceIdOrAlias); + } + return getSpaceLobbyPath(spaceIdOrAlias); +}; export const getSpaceSearchPath = (spaceIdOrAlias: string): string => { const params = { spaceIdOrAlias: encodeURIComponent(spaceIdOrAlias), diff --git a/src/app/pages/paths.ts b/src/app/pages/paths.ts index 6e74f4d..d0ed020 100644 --- a/src/app/pages/paths.ts +++ b/src/app/pages/paths.ts @@ -22,6 +22,7 @@ export const RESET_PASSWORD_PATH = '/reset-password/:server?/'; export const _CREATE_PATH = 'create/'; export const _JOIN_PATH = 'join/'; export const _LOBBY_PATH = 'lobby/'; +export const _FEED_PATH = 'feed/'; /** * array of rooms and senders mxId assigned * to search param as string should be "," separated @@ -57,6 +58,7 @@ export const DIRECT_ROOM_PATH = `/direct/${_ROOM_PATH}`; export const SPACE_PATH = '/:spaceIdOrAlias/'; export const SPACE_LOBBY_PATH = `/:spaceIdOrAlias/${_LOBBY_PATH}`; +export const SPACE_FEED_PATH = `/:spaceIdOrAlias/${_FEED_PATH}`; export const SPACE_SEARCH_PATH = `/:spaceIdOrAlias/${_SEARCH_PATH}`; export const SPACE_ROOM_PATH = `/:spaceIdOrAlias/${_ROOM_PATH}`;