forked from element-hq/element-web
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRoomListView.tsx
More file actions
119 lines (109 loc) · 4.21 KB
/
RoomListView.tsx
File metadata and controls
119 lines (109 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
* Copyright 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import React, { type JSX, type ReactNode } from "react";
import { useViewModel, type ViewModel } from "../../core/viewmodel";
import { RoomListPrimaryFilters, type FilterId } from "../RoomListPrimaryFilters";
import { RoomListLoadingSkeleton } from "./RoomListLoadingSkeleton";
import { RoomListEmptyStateView } from "./RoomListEmptyStateView";
import { VirtualizedRoomListView, type RoomListViewState } from "../VirtualizedRoomListView";
import {
type Room,
type RoomListItemViewModel,
} from "../VirtualizedRoomListView/RoomListItemAccessibilityWrapper/RoomListItemView";
import { type RoomListSectionHeaderViewModel } from "../VirtualizedRoomListView/RoomListSectionHeaderView";
export type RoomListSection = {
/** Unique identifier for the section */
id: string;
/** Array of room IDs that belong to this section */
roomIds: string[];
};
/**
* Snapshot for the room list view
*/
export type RoomListViewSnapshot = {
/** Whether the rooms are currently loading */
isLoadingRooms: boolean;
/** Whether the room list is empty */
isRoomListEmpty: boolean;
/** Array of filter IDs */
filterIds: FilterId[];
/** Currently active filter ID (if any) */
activeFilterId?: FilterId;
/** Room list state */
roomListState: RoomListViewState;
/** Array of sections in the room list */
sections: RoomListSection[];
/** Optional description for the empty state */
emptyStateDescription?: string;
/** Optional action element for the empty state */
emptyStateAction?: ReactNode;
/** Whether the user can create rooms */
canCreateRoom?: boolean;
/** Whether the room list is displayed as a flat list */
isFlatList: boolean;
};
/**
* Actions interface for room list operations
*/
export interface RoomListViewActions {
/** Called when a filter is toggled */
onToggleFilter: (filterId: FilterId) => void;
/** Called to create a new chat room */
createChatRoom: () => void;
/** Called to create a new room */
createRoom: () => void;
/**
* Get view model for a specific room (virtualization API)
* Allow undefined to be returned if we don't have a view model for the room. In this case the room will not be rendered.
*/
getRoomItemViewModel: (roomId: string) => RoomListItemViewModel | undefined;
/** Called when the visible range changes (virtualization API) */
updateVisibleRooms: (startIndex: number, endIndex: number) => void;
/** Get view model for a specific section header (virtualization API) */
getSectionHeaderViewModel: (sectionId: string) => RoomListSectionHeaderViewModel;
}
/**
* The view model type for the room list view
*/
export type RoomListViewModel = ViewModel<RoomListViewSnapshot, RoomListViewActions>;
/**
* Props for RoomListView component
*/
export interface RoomListViewProps {
/** The view model containing all data and callbacks */
vm: RoomListViewModel;
/** Render function for room avatar */
renderAvatar: (room: Room) => ReactNode;
/** Optional callback for keyboard events on the room list */
onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
}
/**
* Room list view component that manages filters, loading states, empty states, and the room list.
*/
export const RoomListView: React.FC<RoomListViewProps> = ({ vm, renderAvatar, onKeyDown }): JSX.Element => {
const snapshot = useViewModel(vm);
let listBody: ReactNode;
if (snapshot.isLoadingRooms) {
listBody = <RoomListLoadingSkeleton />;
} else if (snapshot.isRoomListEmpty) {
listBody = <RoomListEmptyStateView vm={vm} />;
} else {
listBody = <VirtualizedRoomListView vm={vm} renderAvatar={renderAvatar} onKeyDown={onKeyDown} />;
}
return (
<>
<div>
<RoomListPrimaryFilters
filterIds={snapshot.filterIds}
activeFilterId={snapshot.activeFilterId}
onToggleFilter={vm.onToggleFilter}
/>
</div>
{listBody}
</>
);
};