mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-04 22:40:29 +03:00
Revert most changes to Space.tsx
This commit is contained in:
parent
eaf70fb79a
commit
efc77ceb44
1 changed files with 47 additions and 216 deletions
|
|
@ -26,7 +26,6 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
||||||
import { JoinRule, Room } from 'matrix-js-sdk';
|
import { JoinRule, Room } from 'matrix-js-sdk';
|
||||||
import { RoomJoinRulesEventContent } from 'matrix-js-sdk/lib/types';
|
import { RoomJoinRulesEventContent } from 'matrix-js-sdk/lib/types';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
import { logger } from 'matrix-js-sdk/lib/logger';
|
|
||||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||||
import { mDirectAtom } from '../../../state/mDirectList';
|
import { mDirectAtom } from '../../../state/mDirectList';
|
||||||
import {
|
import {
|
||||||
|
|
@ -46,8 +45,7 @@ import {
|
||||||
import { useSpace } from '../../../hooks/useSpace';
|
import { useSpace } from '../../../hooks/useSpace';
|
||||||
import { VirtualTile } from '../../../components/virtualizer';
|
import { VirtualTile } from '../../../components/virtualizer';
|
||||||
import { RoomNavCategoryButton, RoomNavItem } from '../../../features/room-nav';
|
import { RoomNavCategoryButton, RoomNavItem } from '../../../features/room-nav';
|
||||||
// Using the original name for clarity when generating space category IDs
|
import { makeNavCategoryId } from '../../../state/closedNavCategories';
|
||||||
import { makeNavCategoryId as makeSpaceNavCategoryId } from '../../../state/closedNavCategories';
|
|
||||||
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
|
||||||
import { useCategoryHandler } from '../../../hooks/useCategoryHandler';
|
import { useCategoryHandler } from '../../../hooks/useCategoryHandler';
|
||||||
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
|
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
|
||||||
|
|
@ -79,118 +77,6 @@ import {
|
||||||
import { useOpenSpaceSettings } from '../../../state/hooks/spaceSettings';
|
import { useOpenSpaceSettings } from '../../../state/hooks/spaceSettings';
|
||||||
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
|
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
|
||||||
import { CallNavStatus } from '../../../features/room-nav/RoomCallNavStatus';
|
import { CallNavStatus } from '../../../features/room-nav/RoomCallNavStatus';
|
||||||
import { getStateEvents } from '../../../utils/room';
|
|
||||||
import { RoomNavUser } from '../../../features/room-nav/RoomNavUser';
|
|
||||||
import { useStateEvents } from '../../../hooks/useStateEvents';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the raw hierarchy from useSpaceJoinedHierarchy into a flat list
|
|
||||||
* suitable for the virtualizer, including collapsible headers for text/voice rooms.
|
|
||||||
* Removes the top-level "Rooms" category header.
|
|
||||||
*
|
|
||||||
* @param hierarchy - The raw hierarchy data (array of { roomId: string }).
|
|
||||||
* @param mx - The Matrix client instance.
|
|
||||||
* @param spaceRoomId - The ID of the root space being viewed.
|
|
||||||
* @param closedCategories - The Set of currently closed category IDs.
|
|
||||||
* @returns An array of processed items for rendering.
|
|
||||||
*/
|
|
||||||
const processHierarchyForVirtualizer = (
|
|
||||||
hierarchy: { roomId: string }[],
|
|
||||||
mx: ReturnType<typeof useMatrixClient>,
|
|
||||||
spaceRoomId: string,
|
|
||||||
closedCategories: Set<string>
|
|
||||||
): Array<{ type: string; key: string; [key: string]: any }> => {
|
|
||||||
const processed: Array<{ type: string; key: string; [key: string]: any }> = [];
|
|
||||||
let currentCategoryRooms = { text: [], voice: [], users: [] };
|
|
||||||
let currentParentId: string = spaceRoomId;
|
|
||||||
|
|
||||||
const addCollectedRoomsToProcessed = (parentId: string) => {
|
|
||||||
const textCategoryId = `${parentId}_text_rooms`;
|
|
||||||
const voiceCategoryId = `${parentId}_call_rooms`;
|
|
||||||
const isTextClosed = closedCategories.has(textCategoryId);
|
|
||||||
const isCallClosed = closedCategories.has(voiceCategoryId);
|
|
||||||
|
|
||||||
if (currentCategoryRooms.text.length > 0) {
|
|
||||||
processed.push({
|
|
||||||
type: 'room_header',
|
|
||||||
title: 'Text Rooms',
|
|
||||||
categoryId: textCategoryId,
|
|
||||||
key: `${parentId}-text-header`,
|
|
||||||
});
|
|
||||||
if (!isTextClosed) {
|
|
||||||
currentCategoryRooms.text.forEach((room) =>
|
|
||||||
processed.push({ type: 'room', room, key: room.roomId })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentCategoryRooms.voice.length > 0) {
|
|
||||||
processed.push({
|
|
||||||
type: 'room_header',
|
|
||||||
title: 'Call Rooms',
|
|
||||||
categoryId: voiceCategoryId,
|
|
||||||
key: `${parentId}-voice-header`,
|
|
||||||
});
|
|
||||||
if (!isCallClosed) {
|
|
||||||
currentCategoryRooms.voice.forEach((room) => {
|
|
||||||
processed.push({ type: 'room', room, key: room.roomId });
|
|
||||||
|
|
||||||
currentCategoryRooms.users.forEach((entry) => {
|
|
||||||
if (entry.room.roomId === room.roomId) {
|
|
||||||
processed.push(entry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentCategoryRooms = { text: [], voice: [], users: [] };
|
|
||||||
};
|
|
||||||
|
|
||||||
hierarchy.forEach((item) => {
|
|
||||||
const room = mx.getRoom(item.roomId);
|
|
||||||
if (!room) {
|
|
||||||
logger.warn(`processHierarchyForVirtualizer: Room not found for ID ${item.roomId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (room.isSpaceRoom()) {
|
|
||||||
addCollectedRoomsToProcessed(currentParentId);
|
|
||||||
currentParentId = room.roomId;
|
|
||||||
if (room.roomId !== spaceRoomId) {
|
|
||||||
const spaceCategoryId = makeSpaceNavCategoryId(spaceRoomId, room.roomId);
|
|
||||||
processed.push({
|
|
||||||
type: 'category',
|
|
||||||
room,
|
|
||||||
categoryId: spaceCategoryId,
|
|
||||||
key: room.roomId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (room.isCallRoom()) {
|
|
||||||
currentCategoryRooms.voice.push(room);
|
|
||||||
getStateEvents(room, 'org.matrix.msc3401.call.member').forEach(({ event }) => {
|
|
||||||
if (Object.entries(event?.content).length !== 0) {
|
|
||||||
if (event.origin_server_ts + event.content.expires > Date.now()) {
|
|
||||||
currentCategoryRooms.users.push({
|
|
||||||
type: 'user',
|
|
||||||
sender: event.sender,
|
|
||||||
key: event.event_id,
|
|
||||||
room,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (!room.isCallRoom()) {
|
|
||||||
currentCategoryRooms.text.push(room);
|
|
||||||
} else {
|
|
||||||
logger.warn(`processHierarchyForVirtualizer: Room ${room.roomId} is neither text nor voice.`);
|
|
||||||
currentCategoryRooms.text.push(room);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addCollectedRoomsToProcessed(currentParentId);
|
|
||||||
|
|
||||||
return processed;
|
|
||||||
};
|
|
||||||
|
|
||||||
type SpaceMenuProps = {
|
type SpaceMenuProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
|
@ -203,7 +89,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
|
||||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||||
const powerLevels = usePowerLevels(room);
|
const powerLevels = usePowerLevels(room);
|
||||||
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
const { getPowerLevel, canDoAction } = usePowerLevelsAPI(powerLevels);
|
||||||
const canInvite = canDoAction('invite', mx.getUserId() ?? '');
|
const canInvite = canDoAction('invite', getPowerLevel(mx.getUserId() ?? ''));
|
||||||
const openSpaceSettings = useOpenSpaceSettings();
|
const openSpaceSettings = useOpenSpaceSettings();
|
||||||
const { navigateRoom } = useRoomNavigate();
|
const { navigateRoom } = useRoomNavigate();
|
||||||
|
|
||||||
|
|
@ -354,6 +240,7 @@ function SpaceHeader() {
|
||||||
return cords;
|
return cords;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageNavHeader>
|
<PageNavHeader>
|
||||||
|
|
@ -430,8 +317,7 @@ export function Space() {
|
||||||
getRoom,
|
getRoom,
|
||||||
useCallback(
|
useCallback(
|
||||||
(parentId, roomId) => {
|
(parentId, roomId) => {
|
||||||
const parentSpaceCategoryId = makeSpaceNavCategoryId(space.roomId, parentId);
|
if (!closedCategories.has(makeNavCategoryId(space.roomId, parentId))) {
|
||||||
if (!closedCategories.has(parentSpaceCategoryId)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const showRoomAnyway = roomToUnread.has(roomId) || roomId === selectedRoomId;
|
const showRoomAnyway = roomToUnread.has(roomId) || roomId === selectedRoomId;
|
||||||
|
|
@ -439,31 +325,14 @@ export function Space() {
|
||||||
},
|
},
|
||||||
[space.roomId, closedCategories, roomToUnread, selectedRoomId]
|
[space.roomId, closedCategories, roomToUnread, selectedRoomId]
|
||||||
),
|
),
|
||||||
|
|
||||||
useCallback(
|
useCallback(
|
||||||
(subCategoryId) => closedCategories.has(makeSpaceNavCategoryId(space.roomId, subCategoryId)),
|
(sId) => closedCategories.has(makeNavCategoryId(space.roomId, sId)),
|
||||||
[closedCategories, space.roomId]
|
[closedCategories, space.roomId]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const callRooms = useMemo(
|
|
||||||
() =>
|
|
||||||
hierarchy
|
|
||||||
.map((item) => mx.getRoom(item.roomId))
|
|
||||||
.filter((room): room is Room => !!room && room.isCallRoom()),
|
|
||||||
[hierarchy, mx]
|
|
||||||
);
|
|
||||||
|
|
||||||
const updateTrigger = useStateEvents(callRooms, StateEvent.GroupCallMemberPrefix);
|
|
||||||
|
|
||||||
const processedHierarchy = useMemo(
|
|
||||||
() => processHierarchyForVirtualizer(hierarchy, mx, space.roomId, closedCategories),
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
[hierarchy, mx, space.roomId, closedCategories, updateTrigger]
|
|
||||||
);
|
|
||||||
|
|
||||||
const virtualizer = useVirtualizer({
|
const virtualizer = useVirtualizer({
|
||||||
count: processedHierarchy.length,
|
count: hierarchy.length,
|
||||||
getScrollElement: () => scrollRef.current,
|
getScrollElement: () => scrollRef.current,
|
||||||
estimateSize: () => 32,
|
estimateSize: () => 32,
|
||||||
overscan: 10,
|
overscan: 10,
|
||||||
|
|
@ -477,12 +346,9 @@ export function Space() {
|
||||||
getSpaceRoomPath(spaceIdOrAlias, getCanonicalAliasOrRoomId(mx, roomId));
|
getSpaceRoomPath(spaceIdOrAlias, getCanonicalAliasOrRoomId(mx, roomId));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageNav style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
<PageNav>
|
||||||
<SpaceHeader />
|
<SpaceHeader />
|
||||||
<PageNavContent
|
<PageNavContent scrollRef={scrollRef}>
|
||||||
scrollRef={scrollRef}
|
|
||||||
style={{ flexGrow: 1, overflowY: 'auto', overflowX: 'hidden' }}
|
|
||||||
>
|
|
||||||
<Box direction="Column" gap="300">
|
<Box direction="Column" gap="300">
|
||||||
<NavCategory>
|
<NavCategory>
|
||||||
<NavItem variant="Background" radii="400" aria-selected={lobbySelected}>
|
<NavItem variant="Background" radii="400" aria-selected={lobbySelected}>
|
||||||
|
|
@ -518,91 +384,56 @@ export function Space() {
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</NavItem>
|
</NavItem>
|
||||||
</NavCategory>
|
</NavCategory>
|
||||||
</Box>
|
|
||||||
<NavCategory
|
<NavCategory
|
||||||
style={{
|
style={{
|
||||||
height: `${virtualizer.getTotalSize()}px`,
|
height: virtualizer.getTotalSize(),
|
||||||
width: '100%',
|
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{virtualizer.getVirtualItems().map((vItem) => {
|
{virtualizer.getVirtualItems().map((vItem) => {
|
||||||
const item = processedHierarchy[vItem.index];
|
const { roomId } = hierarchy[vItem.index] ?? {};
|
||||||
if (!item) return null;
|
const room = mx.getRoom(roomId);
|
||||||
const renderContent = () => {
|
if (!room) return null;
|
||||||
switch (item.type) {
|
|
||||||
case 'category': {
|
if (room.isSpaceRoom()) {
|
||||||
const { room, categoryId } = item;
|
const categoryId = makeNavCategoryId(space.roomId, roomId);
|
||||||
const { name } = room;
|
|
||||||
const paddingTop = config?.space?.S400 ?? '1rem';
|
|
||||||
return (
|
return (
|
||||||
<div style={{ paddingTop }}>
|
<VirtualTile
|
||||||
|
virtualItem={vItem}
|
||||||
|
key={vItem.index}
|
||||||
|
ref={virtualizer.measureElement}
|
||||||
|
>
|
||||||
|
<div style={{ paddingTop: vItem.index === 0 ? undefined : config.space.S400 }}>
|
||||||
<NavCategoryHeader>
|
<NavCategoryHeader>
|
||||||
<RoomNavCategoryButton
|
<RoomNavCategoryButton
|
||||||
data-category-id={categoryId}
|
data-category-id={categoryId}
|
||||||
onClick={handleCategoryClick}
|
onClick={handleCategoryClick}
|
||||||
closed={closedCategories.has(categoryId)}
|
closed={closedCategories.has(categoryId)}
|
||||||
>
|
>
|
||||||
{name}
|
{roomId === space.roomId ? 'Rooms' : room?.name}
|
||||||
</RoomNavCategoryButton>
|
</RoomNavCategoryButton>
|
||||||
</NavCategoryHeader>
|
</NavCategoryHeader>
|
||||||
</div>
|
</div>
|
||||||
|
</VirtualTile>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case 'room_header': {
|
|
||||||
const { title, categoryId } = item;
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<NavCategoryHeader variant="Subtle">
|
|
||||||
<RoomNavCategoryButton
|
|
||||||
data-category-id={categoryId}
|
|
||||||
onClick={handleCategoryClick}
|
|
||||||
closed={closedCategories.has(categoryId)}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</RoomNavCategoryButton>
|
|
||||||
</NavCategoryHeader>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case 'room': {
|
|
||||||
const { room } = item;
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<RoomNavItem
|
|
||||||
room={room}
|
|
||||||
selected={selectedRoomId === room.roomId}
|
|
||||||
showAvatar={mDirects.has(room.roomId)}
|
|
||||||
direct={mDirects.has(room.roomId)}
|
|
||||||
linkPath={getToLink(room.roomId)}
|
|
||||||
notificationMode={getRoomNotificationMode(
|
|
||||||
notificationPreferences,
|
|
||||||
room.roomId
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case 'user': {
|
|
||||||
const { sender, room } = item;
|
|
||||||
return (
|
|
||||||
<Box style={{ paddingLeft: config.space.S200 }}>
|
|
||||||
<RoomNavUser room={room} space={space} sender={sender} />
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VirtualTile virtualItem={vItem} key={item.key} ref={virtualizer.measureElement}>
|
<VirtualTile virtualItem={vItem} key={vItem.index} ref={virtualizer.measureElement}>
|
||||||
{renderContent()}
|
<RoomNavItem
|
||||||
|
room={room}
|
||||||
|
selected={selectedRoomId === roomId}
|
||||||
|
showAvatar={mDirects.has(roomId)}
|
||||||
|
direct={mDirects.has(roomId)}
|
||||||
|
linkPath={getToLink(roomId)}
|
||||||
|
notificationMode={getRoomNotificationMode(notificationPreferences, room.roomId)}
|
||||||
|
/>
|
||||||
</VirtualTile>
|
</VirtualTile>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</NavCategory>
|
</NavCategory>
|
||||||
|
</Box>
|
||||||
</PageNavContent>
|
</PageNavContent>
|
||||||
<CallNavStatus />
|
<CallNavStatus />
|
||||||
</PageNav>
|
</PageNav>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue