add loading state to view model and spinner to room list vieqw

This commit is contained in:
David Langley
2025-04-11 17:57:17 +01:00
parent c929eedd81
commit c6b1a09b55
7 changed files with 24 additions and 2 deletions

View File

@@ -21,6 +21,11 @@ import { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import { useStickyRoomList } from "./useStickyRoomList";
export interface RoomListViewState {
/**
* Whether the list of rooms is being loaded.
*/
isLoadingRooms: boolean;
/**
* A list of rooms to be displayed in the left panel.
*/
@@ -98,6 +103,7 @@ export interface RoomListViewState {
export function useRoomListViewModel(): RoomListViewState {
const matrixClient = useMatrixClientContext();
const {
isLoadingRooms,
primaryFilters,
activePrimaryFilter,
rooms: filteredRooms,
@@ -120,6 +126,7 @@ export function useRoomListViewModel(): RoomListViewState {
const createRoom = useCallback(() => createRoomFunc(currentSpace), [currentSpace]);
return {
isLoadingRooms,
rooms,
canCreateRoom,
createRoom,

View File

@@ -35,6 +35,7 @@ export interface PrimaryFilter {
interface FilteredRooms {
primaryFilters: PrimaryFilter[];
isLoadingRooms: boolean;
rooms: Room[];
activateSecondaryFilter: (filter: SecondaryFilters) => void;
activeSecondaryFilter: SecondaryFilters;
@@ -115,6 +116,7 @@ export function useFilteredRooms(): FilteredRooms {
);
const [rooms, setRooms] = useState(() => RoomListStoreV3.instance.getSortedRoomsInActiveSpace());
const [isLoadingRooms, setIsLoadingRooms] = useState(true);
const updateRoomsFromStore = useCallback((filters: FilterKey[] = []): void => {
const newRooms = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(filters);
@@ -135,6 +137,7 @@ export function useFilteredRooms(): FilteredRooms {
};
useEventEmitter(RoomListStoreV3.instance, LISTS_UPDATE_EVENT, () => {
setIsLoadingRooms(false);
const filters = getAppliedFilters();
updateRoomsFromStore(filters);
});
@@ -194,5 +197,12 @@ export function useFilteredRooms(): FilteredRooms {
const activePrimaryFilter = useMemo(() => primaryFilters.find((filter) => filter.active), [primaryFilters]);
return { primaryFilters, activePrimaryFilter, rooms, activateSecondaryFilter, activeSecondaryFilter };
return {
isLoadingRooms,
primaryFilters,
activePrimaryFilter,
rooms,
activateSecondaryFilter,
activeSecondaryFilter,
};
}

View File

@@ -11,6 +11,7 @@ import { useRoomListViewModel } from "../../../viewmodels/roomlist/RoomListViewM
import { RoomList } from "./RoomList";
import { EmptyRoomList } from "./EmptyRoomList";
import { RoomListPrimaryFilters } from "./RoomListPrimaryFilters";
import Spinner from "../../elements/Spinner";
/**
* Host the room list and the (future) room filters
@@ -22,7 +23,7 @@ export function RoomListView(): JSX.Element {
return (
<>
<RoomListPrimaryFilters vm={vm} />
{isRoomListEmpty ? <EmptyRoomList vm={vm} /> : <RoomList vm={vm} />}
{vm.isLoadingRooms ? <Spinner /> : isRoomListEmpty ? <EmptyRoomList vm={vm} /> : <RoomList vm={vm} />}
</>
);
}

View File

@@ -20,6 +20,7 @@ describe("<EmptyRoomList />", () => {
beforeEach(() => {
vm = {
isLoadingRooms: false,
rooms: [],
primaryFilters: [],
activateSecondaryFilter: jest.fn().mockReturnValue({}),

View File

@@ -29,6 +29,7 @@ describe("<RoomList />", () => {
matrixClient = stubClient();
const rooms = Array.from({ length: 10 }, (_, i) => mkRoom(matrixClient, `room${i}`));
vm = {
isLoadingRooms: false,
rooms,
primaryFilters: [],
activateSecondaryFilter: () => {},

View File

@@ -20,6 +20,7 @@ describe("<RoomListPrimaryFilters />", () => {
beforeEach(() => {
vm = {
isLoadingRooms: false,
rooms: [],
canCreateRoom: true,
createRoom: jest.fn(),

View File

@@ -24,6 +24,7 @@ jest.mock("../../../../../../src/components/viewmodels/roomlist/RoomListViewMode
describe("<RoomListView />", () => {
const defaultValue: RoomListViewState = {
isLoadingRooms: false,
rooms: [],
primaryFilters: [],
activateSecondaryFilter: jest.fn().mockReturnValue({}),