Files
ThreadNet-Web/packages/shared-components/src/room-list/RoomListView/RoomListView.tsx
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

102 lines
3.5 KiB
TypeScript
Raw Normal View History

/*
* 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 "../../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 RoomItemViewModel } from "../RoomListItemView";
/**
* Snapshot for the room list view
*/
export type RoomListSnapshot = {
/** 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 room IDs for virtualization */
roomIds: string[];
/** 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;
};
/**
* 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) */
getRoomItemViewModel: (roomId: string) => RoomItemViewModel;
/** Called when the visible range changes (virtualization API) */
updateVisibleRooms: (startIndex: number, endIndex: number) => void;
}
/**
* The view model type for the room list view
*/
export type RoomListViewModel = ViewModel<RoomListSnapshot, 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}
</>
);
};