diff --git a/src/app/features/lobby/Lobby.tsx b/src/app/features/lobby/Lobby.tsx index 4c3514f83..c43fae671 100644 --- a/src/app/features/lobby/Lobby.tsx +++ b/src/app/features/lobby/Lobby.tsx @@ -17,7 +17,7 @@ import { produce } from 'immer'; import { useSpace } from '$hooks/useSpace'; import { Page, PageContent, PageContentCenter, PageHeroSection } from '$components/page'; import type { HierarchyItem, HierarchyItemSpace } from '$hooks/useSpaceHierarchy'; -import { useSpaceHierarchy } from '$hooks/useSpaceHierarchy'; +import { getSpaceHierarchyItemKey, useSpaceHierarchy } from '$hooks/useSpaceHierarchy'; import { VirtualTile } from '$components/virtualizer'; import { spaceRoomsAtom } from '$state/spaceRooms'; import { useSetting } from '$state/hooks/settings'; @@ -301,7 +301,7 @@ export function Lobby() { (index: number) => { const item = hierarchy[index]; if (!item) return index; - return `${space.roomId}:${item.space.roomId}:${item.space.depth}`; + return getSpaceHierarchyItemKey(space.roomId, item.space); }, [hierarchy, space.roomId] ); diff --git a/src/app/hooks/useSpaceHierarchy.test.ts b/src/app/hooks/useSpaceHierarchy.test.ts new file mode 100644 index 000000000..6b67d91cf --- /dev/null +++ b/src/app/hooks/useSpaceHierarchy.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest'; +import { getSpaceHierarchyItemKey } from './useSpaceHierarchy'; + +describe('getSpaceHierarchyItemKey', () => { + it('distinguishes hierarchy entries included through separate parents at the same depth', () => { + const firstHierarchyItem = { + roomId: '!child:example.com', + parentId: '!first-subspace:example.com', + content: { via: [] }, + ts: 0, + depth: 1, + }; + const secondHierarchyItem = { + ...firstHierarchyItem, + parentId: '!second-subspace:example.com', + }; + + expect(getSpaceHierarchyItemKey('!space:example.com', firstHierarchyItem)).not.toBe( + getSpaceHierarchyItemKey('!space:example.com', secondHierarchyItem) + ); + }); +}); diff --git a/src/app/hooks/useSpaceHierarchy.ts b/src/app/hooks/useSpaceHierarchy.ts index 81d51d1a2..b4ab4faab 100644 --- a/src/app/hooks/useSpaceHierarchy.ts +++ b/src/app/hooks/useSpaceHierarchy.ts @@ -35,6 +35,9 @@ export type HierarchyItemRoom = { export type HierarchyItem = HierarchyItemSpace | HierarchyItemRoom; +export const getSpaceHierarchyItemKey = (spaceId: string, item: HierarchyItem): string => + `${spaceId}:${item.parentId ?? ''}:${item.roomId}:${item.depth}`; + type GetRoomCallback = (roomId: string) => Room | undefined; const hierarchyItemSort: SortFunc = (a, b) => { diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index 744530b5e..80e0a9de3 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -36,7 +36,7 @@ import { useCategoryHandler } from '$hooks/useCategoryHandler'; import { useNavToActivePathMapper } from '$hooks/useNavToActivePathMapper'; import { useRoomName } from '$hooks/useRoomMeta'; import type { HierarchyItem } from '$hooks/useSpaceHierarchy'; -import { useSpaceJoinedHierarchy } from '$hooks/useSpaceHierarchy'; +import { getSpaceHierarchyItemKey, useSpaceJoinedHierarchy } from '$hooks/useSpaceHierarchy'; import { allRoomsAtom } from '$state/room-list/roomList'; import { PageNavContent, PageNavHeader } from '$components/page'; import { PageNavShell } from '$components/page/PageNavShell'; @@ -779,7 +779,7 @@ export function Space() { (index: number) => { const item = hierarchy[index]; if (!item) return index; - return `${space.roomId}:${item.roomId}:${item.depth}`; + return getSpaceHierarchyItemKey(space.roomId, item); }, [hierarchy, space.roomId] );