Room list: add sections to shared components (#32735)
* feat: add section header * refactor: remove index and role related to list box from RoomListItemView * feat: add wrapper to RoomListItemView to handle different accessiblity pattern * feat: add section support to VirtualizedRoomListView * feat: add sections support to RoomListView * test: add screenshot for sections header * test: add/update screenshots for sections * feat: force flat list on view model This is an intermediary step before implementing sections in the vm. We force the flat list but we use the underneath the view supporting sections. * test: update RoomListViewModel test * test: fix breaking test * chore: rename `getSectionViewModel` to `getSectionHeaderViewModel` * chore: add missing `RoomListItemAccessibilityWrapper` export * chore: merge `react` imports * chore: simplify and add comment to `getItemKey` and `getHeaderKey` * chore add comments to `getItemComponent` variants * chore: fix typo in example doc
This commit is contained in:
@@ -61,6 +61,8 @@ export class RoomListViewViewModel
|
||||
const roomsResult = RoomListStoreV3.instance.getSortedRoomsInActiveSpace(undefined);
|
||||
const canCreateRoom = hasCreateRoomRights(props.client, activeSpace);
|
||||
const filterIds = [...filterKeyToIdMap.values()];
|
||||
const roomIds = roomsResult.rooms.map((room) => room.roomId);
|
||||
const sections = [{ id: "all", roomIds }];
|
||||
|
||||
super(props, {
|
||||
// Initial view state - start with empty, will populate in async init
|
||||
@@ -73,7 +75,9 @@ export class RoomListViewViewModel
|
||||
spaceId: roomsResult.spaceId,
|
||||
filterKeys: undefined,
|
||||
},
|
||||
roomIds: roomsResult.rooms.map((room) => room.roomId),
|
||||
// Until we implement sections, this view model only supports the flat list mode
|
||||
isFlatList: true,
|
||||
sections,
|
||||
canCreateRoom,
|
||||
});
|
||||
|
||||
@@ -195,6 +199,15 @@ export class RoomListViewViewModel
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not implemented - this view model does not support sections.
|
||||
* Flat list mode is forced so this method is never be called.
|
||||
* @throw Error if called
|
||||
*/
|
||||
public getSectionHeaderViewModel(): never {
|
||||
throw new Error("Sections are not supported in this room list");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update which rooms are currently visible.
|
||||
* Called by the view when scroll position changes.
|
||||
@@ -408,6 +421,7 @@ export class RoomListViewViewModel
|
||||
// Build the complete state atomically to ensure consistency
|
||||
// roomIds and roomListState must always be in sync
|
||||
const roomIds = this.roomIds;
|
||||
const sections = [{ id: "all", roomIds }];
|
||||
|
||||
// Update filter keys - only update if they have actually changed to prevent unnecessary re-renders of the room list
|
||||
const previousFilterKeys = this.snapshot.current.roomListState.filterKeys;
|
||||
@@ -428,7 +442,7 @@ export class RoomListViewViewModel
|
||||
isRoomListEmpty,
|
||||
activeFilterId,
|
||||
roomListState,
|
||||
roomIds,
|
||||
sections,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ describe("RoomListViewViewModel", () => {
|
||||
viewModel = new RoomListViewViewModel({ client: matrixClient });
|
||||
|
||||
const snapshot = viewModel.getSnapshot();
|
||||
expect(snapshot.roomIds).toEqual(["!room1:server", "!room2:server", "!room3:server"]);
|
||||
expect(snapshot.sections[0].roomIds).toEqual(["!room1:server", "!room2:server", "!room3:server"]);
|
||||
expect(snapshot.isRoomListEmpty).toBe(false);
|
||||
expect(snapshot.isLoadingRooms).toBe(false);
|
||||
expect(snapshot.roomListState.spaceId).toBe("home");
|
||||
@@ -82,7 +82,7 @@ describe("RoomListViewViewModel", () => {
|
||||
|
||||
viewModel = new RoomListViewViewModel({ client: matrixClient });
|
||||
|
||||
expect(viewModel.getSnapshot().roomIds).toEqual([]);
|
||||
expect(viewModel.getSnapshot().sections[0].roomIds).toEqual([]);
|
||||
expect(viewModel.getSnapshot().isRoomListEmpty).toBe(true);
|
||||
});
|
||||
|
||||
@@ -106,7 +106,7 @@ describe("RoomListViewViewModel", () => {
|
||||
|
||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
||||
|
||||
expect(viewModel.getSnapshot().roomIds).toEqual([
|
||||
expect(viewModel.getSnapshot().sections[0].roomIds).toEqual([
|
||||
"!room1:server",
|
||||
"!room2:server",
|
||||
"!room3:server",
|
||||
@@ -156,7 +156,7 @@ describe("RoomListViewViewModel", () => {
|
||||
RoomListStoreV3.instance.emit(RoomListStoreV3Event.ListsUpdate);
|
||||
|
||||
expect(viewModel.getSnapshot().roomListState.spaceId).toBe("!space:server");
|
||||
expect(viewModel.getSnapshot().roomIds).toEqual(["!room1:server", "!room2:server"]);
|
||||
expect(viewModel.getSnapshot().sections[0].roomIds).toEqual(["!room1:server", "!room2:server"]);
|
||||
});
|
||||
|
||||
it("should clear view models when space changes", () => {
|
||||
@@ -240,7 +240,7 @@ describe("RoomListViewViewModel", () => {
|
||||
|
||||
// Active room should still be at index 1 (sticky behavior)
|
||||
expect(viewModel.getSnapshot().roomListState.activeRoomIndex).toBe(1);
|
||||
expect(viewModel.getSnapshot().roomIds[1]).toBe("!room2:server");
|
||||
expect(viewModel.getSnapshot().sections[0].roomIds[1]).toBe("!room2:server");
|
||||
});
|
||||
|
||||
it("should not apply sticky behavior when user changes rooms", async () => {
|
||||
@@ -283,7 +283,7 @@ describe("RoomListViewViewModel", () => {
|
||||
viewModel.onToggleFilter("unread");
|
||||
|
||||
expect(viewModel.getSnapshot().activeFilterId).toBe("unread");
|
||||
expect(viewModel.getSnapshot().roomIds).toEqual(["!room1:server"]);
|
||||
expect(viewModel.getSnapshot().sections[0].roomIds).toEqual(["!room1:server"]);
|
||||
});
|
||||
|
||||
it("should toggle filter off", () => {
|
||||
@@ -307,7 +307,11 @@ describe("RoomListViewViewModel", () => {
|
||||
viewModel.onToggleFilter("unread");
|
||||
|
||||
expect(viewModel.getSnapshot().activeFilterId).toBeUndefined();
|
||||
expect(viewModel.getSnapshot().roomIds).toEqual(["!room1:server", "!room2:server", "!room3:server"]);
|
||||
expect(viewModel.getSnapshot().sections[0].roomIds).toEqual([
|
||||
"!room1:server",
|
||||
"!room2:server",
|
||||
"!room3:server",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user