diff --git a/src/app/features/lobby/Lobby.tsx b/src/app/features/lobby/Lobby.tsx index 6851873f..709334a5 100644 --- a/src/app/features/lobby/Lobby.tsx +++ b/src/app/features/lobby/Lobby.tsx @@ -199,10 +199,18 @@ export function Lobby() { * * @param spaceId - The root space ID. * @param parentId - The parent space ID to start the check from. + * @param previousId - The last ID checked, only used to ignore root collapse state. * @returns True if parentId or all ancestors is in a closed category. */ const getInClosedCategories = useCallback( - (spaceId: string, parentId: string): boolean => { + (spaceId: string, parentId: string, previousId?: string): boolean => { + // Ignore root space being collapsed if in a subspace, + // this is due to many spaces dumping all rooms in the top-level space. + if (parentId === spaceId) { + if (previousId) { + if (getRoom(previousId)?.isSpaceRoom() || spaceRooms.has(previousId)) return false; + } + } if (closedCategories.has(makeLobbyCategoryId(spaceId, parentId))) { return true; } @@ -214,16 +222,40 @@ export function Lobby() { let anyOpen = false; parentParentIds.forEach((id) => { - if (!getInClosedCategories(spaceId, id)) { + if (!getInClosedCategories(spaceId, id, parentId)) { anyOpen = true; } }); return !anyOpen; }, - [closedCategories, roomToParents] + [closedCategories, getRoom, roomToParents, spaceRooms] ); + /** + * Determines whether all parent categories are collapsed. + * + * @param spaceId - The root space ID. + * @param roomId - The room ID to start the check from. + * @returns True if every parent category is collapsed; false otherwise. + */ + + const getAllAncestorsCollapsed = (spaceId: string, roomId: string): boolean => { + const parentIds = roomToParents.get(roomId); + + if (!parentIds || parentIds.size === 0) { + return false; + } + + let allCollapsed = true; + parentIds.forEach((id) => { + if (!getInClosedCategories(spaceId, id, roomId)) { + allCollapsed = false; + } + }); + return allCollapsed; + }; + const [draggingItem, setDraggingItem] = useState(); const hierarchy = useSpaceHierarchy( space.roomId, @@ -443,9 +475,18 @@ export function Lobby() { [setSpaceRooms] ); - const handleCategoryClick = useCategoryHandler(setClosedCategories, (categoryId) => - closedCategories.has(categoryId) - ); + const handleCategoryClick = useCategoryHandler(setClosedCategories, (categoryId) => { + const collapsed = closedCategories.has(categoryId); + const [spaceId, roomId] = categoryId.split('|').slice(-2); + + // Only prevent collapsing if all parents are collapsed + const toggleable = !getAllAncestorsCollapsed(spaceId, roomId); + + if (toggleable) { + return collapsed; + } + return !collapsed; + }); const handleOpenRoom: MouseEventHandler = (evt) => { const rId = evt.currentTarget.getAttribute('data-room-id'); diff --git a/src/app/pages/client/space/Space.tsx b/src/app/pages/client/space/Space.tsx index bb79dcac..c99ed4bc 100644 --- a/src/app/pages/client/space/Space.tsx +++ b/src/app/pages/client/space/Space.tsx @@ -321,7 +321,15 @@ export function Space() { * @returns True if parentId or all ancestors is in a closed category. */ const getInClosedCategories = useCallback( - (spaceId: string, parentId: string): boolean => { + (spaceId: string, parentId: string, previousId?: string): boolean => { + // Ignore root space being collapsed if in a subspace, + // this is due to many spaces dumping all rooms in the top-level space. + if (parentId === spaceId) { + if (previousId) { + if (getRoom(previousId)?.isSpaceRoom()) return false; + } + } + if (closedCategories.has(makeNavCategoryId(spaceId, parentId))) { return true; } @@ -333,14 +341,14 @@ export function Space() { let anyOpen = false; parentParentIds.forEach((id) => { - if (!getInClosedCategories(spaceId, id)) { + if (!getInClosedCategories(spaceId, id, parentId)) { anyOpen = true; } }); return !anyOpen; }, - [closedCategories, roomToParents] + [closedCategories, getRoom, roomToParents] ); // There are better ways to do this @@ -402,7 +410,7 @@ export function Space() { let allCollapsed = true; parentIds.forEach((id) => { - if (!getInClosedCategories(spaceId, id)) { + if (!getInClosedCategories(spaceId, id, roomId)) { allCollapsed = false; } }); @@ -414,7 +422,7 @@ export function Space() { getRoom, useCallback( (parentId, roomId) => { - if (!getInClosedCategories(space.roomId, parentId)) { + if (!getInClosedCategories(space.roomId, parentId, roomId)) { return false; } if (getContainsShowRoom(roomId)) return false; @@ -423,7 +431,7 @@ export function Space() { [getContainsShowRoom, getInClosedCategories, space.roomId] ), useCallback( - (sId) => getInClosedCategories(space.roomId, sId), + (sId) => getInClosedCategories(space.roomId, sId, sId), [getInClosedCategories, space.roomId] ) );