1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-09 10:22:46 +03:00

Merge pull request #2628 from matrix-org/kegan/ss-member-counts

sliding sync: add invited|joined_count
This commit is contained in:
kegsay
2022-09-07 11:22:47 +02:00
committed by GitHub
3 changed files with 64 additions and 2 deletions

View File

@@ -168,6 +168,7 @@ describe("SlidingSyncSdk", () => {
const roomD = "!d_with_notif_count:localhost"; const roomD = "!d_with_notif_count:localhost";
const roomE = "!e_with_invite:localhost"; const roomE = "!e_with_invite:localhost";
const roomF = "!f_calc_room_name:localhost"; const roomF = "!f_calc_room_name:localhost";
const roomG = "!g_join_invite_counts:localhost";
const data: Record<string, MSC3575RoomData> = { const data: Record<string, MSC3575RoomData> = {
[roomA]: { [roomA]: {
name: "A", name: "A",
@@ -261,12 +262,25 @@ describe("SlidingSyncSdk", () => {
], ],
initial: true, initial: true,
}, },
[roomG]: {
name: "G",
required_state: [],
timeline: [
mkOwnStateEvent(EventType.RoomCreate, { creator: selfUserId }, ""),
mkOwnStateEvent(EventType.RoomMember, { membership: "join" }, selfUserId),
mkOwnStateEvent(EventType.RoomPowerLevels, { users: { [selfUserId]: 100 } }, ""),
],
joined_count: 5,
invited_count: 2,
initial: true,
},
}; };
it("can be created with required_state and timeline", () => { it("can be created with required_state and timeline", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomA, data[roomA]); mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomA, data[roomA]);
const gotRoom = client.getRoom(roomA); const gotRoom = client.getRoom(roomA);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.name).toEqual(data[roomA].name); expect(gotRoom.name).toEqual(data[roomA].name);
expect(gotRoom.getMyMembership()).toEqual("join"); expect(gotRoom.getMyMembership()).toEqual("join");
assertTimelineEvents(gotRoom.getLiveTimeline().getEvents().slice(-2), data[roomA].timeline); assertTimelineEvents(gotRoom.getLiveTimeline().getEvents().slice(-2), data[roomA].timeline);
@@ -276,6 +290,7 @@ describe("SlidingSyncSdk", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomB, data[roomB]); mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomB, data[roomB]);
const gotRoom = client.getRoom(roomB); const gotRoom = client.getRoom(roomB);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.name).toEqual(data[roomB].name); expect(gotRoom.name).toEqual(data[roomB].name);
expect(gotRoom.getMyMembership()).toEqual("join"); expect(gotRoom.getMyMembership()).toEqual("join");
assertTimelineEvents(gotRoom.getLiveTimeline().getEvents().slice(-5), data[roomB].timeline); assertTimelineEvents(gotRoom.getLiveTimeline().getEvents().slice(-5), data[roomB].timeline);
@@ -285,6 +300,7 @@ describe("SlidingSyncSdk", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomC, data[roomC]); mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomC, data[roomC]);
const gotRoom = client.getRoom(roomC); const gotRoom = client.getRoom(roomC);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect( expect(
gotRoom.getUnreadNotificationCount(NotificationCountType.Highlight), gotRoom.getUnreadNotificationCount(NotificationCountType.Highlight),
).toEqual(data[roomC].highlight_count); ).toEqual(data[roomC].highlight_count);
@@ -294,15 +310,26 @@ describe("SlidingSyncSdk", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomD, data[roomD]); mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomD, data[roomD]);
const gotRoom = client.getRoom(roomD); const gotRoom = client.getRoom(roomD);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect( expect(
gotRoom.getUnreadNotificationCount(NotificationCountType.Total), gotRoom.getUnreadNotificationCount(NotificationCountType.Total),
).toEqual(data[roomD].notification_count); ).toEqual(data[roomD].notification_count);
}); });
it("can be created with an invited/joined_count", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomG, data[roomG]);
const gotRoom = client.getRoom(roomG);
expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.getInvitedMemberCount()).toEqual(data[roomG].invited_count);
expect(gotRoom.getJoinedMemberCount()).toEqual(data[roomG].joined_count);
});
it("can be created with invite_state", () => { it("can be created with invite_state", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomE, data[roomE]); mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomE, data[roomE]);
const gotRoom = client.getRoom(roomE); const gotRoom = client.getRoom(roomE);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.getMyMembership()).toEqual("invite"); expect(gotRoom.getMyMembership()).toEqual("invite");
expect(gotRoom.currentState.getJoinRule()).toEqual(JoinRule.Invite); expect(gotRoom.currentState.getJoinRule()).toEqual(JoinRule.Invite);
}); });
@@ -311,6 +338,7 @@ describe("SlidingSyncSdk", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomF, data[roomF]); mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomF, data[roomF]);
const gotRoom = client.getRoom(roomF); const gotRoom = client.getRoom(roomF);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect( expect(
gotRoom.name, gotRoom.name,
).toEqual(data[roomF].name); ).toEqual(data[roomF].name);
@@ -326,6 +354,7 @@ describe("SlidingSyncSdk", () => {
}); });
const gotRoom = client.getRoom(roomA); const gotRoom = client.getRoom(roomA);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
const newTimeline = data[roomA].timeline; const newTimeline = data[roomA].timeline;
newTimeline.push(newEvent); newTimeline.push(newEvent);
assertTimelineEvents(gotRoom.getLiveTimeline().getEvents().slice(-3), newTimeline); assertTimelineEvents(gotRoom.getLiveTimeline().getEvents().slice(-3), newTimeline);
@@ -333,6 +362,8 @@ describe("SlidingSyncSdk", () => {
it("can update with a new required_state event", async () => { it("can update with a new required_state event", async () => {
let gotRoom = client.getRoom(roomB); let gotRoom = client.getRoom(roomB);
expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.getJoinRule()).toEqual(JoinRule.Invite); // default expect(gotRoom.getJoinRule()).toEqual(JoinRule.Invite); // default
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomB, { mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomB, {
required_state: [ required_state: [
@@ -343,6 +374,7 @@ describe("SlidingSyncSdk", () => {
}); });
gotRoom = client.getRoom(roomB); gotRoom = client.getRoom(roomB);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.getJoinRule()).toEqual(JoinRule.Restricted); expect(gotRoom.getJoinRule()).toEqual(JoinRule.Restricted);
}); });
@@ -355,6 +387,7 @@ describe("SlidingSyncSdk", () => {
}); });
const gotRoom = client.getRoom(roomC); const gotRoom = client.getRoom(roomC);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect( expect(
gotRoom.getUnreadNotificationCount(NotificationCountType.Highlight), gotRoom.getUnreadNotificationCount(NotificationCountType.Highlight),
).toEqual(1); ).toEqual(1);
@@ -369,11 +402,25 @@ describe("SlidingSyncSdk", () => {
}); });
const gotRoom = client.getRoom(roomD); const gotRoom = client.getRoom(roomD);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect( expect(
gotRoom.getUnreadNotificationCount(NotificationCountType.Total), gotRoom.getUnreadNotificationCount(NotificationCountType.Total),
).toEqual(1); ).toEqual(1);
}); });
it("can update with a new joined_count", () => {
mockSlidingSync.emit(SlidingSyncEvent.RoomData, roomG, {
name: data[roomD].name,
required_state: [],
timeline: [],
joined_count: 1,
});
const gotRoom = client.getRoom(roomG);
expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
expect(gotRoom.getJoinedMemberCount()).toEqual(1);
});
// Regression test for a bug which caused the timeline entries to be out-of-order // Regression test for a bug which caused the timeline entries to be out-of-order
// when the same room appears twice with different timeline limits. E.g appears in // when the same room appears twice with different timeline limits. E.g appears in
// the list with timeline_limit:1 then appears again as a room subscription with // the list with timeline_limit:1 then appears again as a room subscription with
@@ -394,6 +441,7 @@ describe("SlidingSyncSdk", () => {
}); });
const gotRoom = client.getRoom(roomA); const gotRoom = client.getRoom(roomA);
expect(gotRoom).toBeDefined(); expect(gotRoom).toBeDefined();
if (gotRoom == null) { return; }
logger.log("want:", oldTimeline.map((e) => (e.type + " : " + (e.content || {}).body))); logger.log("want:", oldTimeline.map((e) => (e.type + " : " + (e.content || {}).body)));
logger.log("got:", gotRoom.getLiveTimeline().getEvents().map( logger.log("got:", gotRoom.getLiveTimeline().getEvents().map(

View File

@@ -293,13 +293,16 @@ export class SlidingSyncSdk {
this.processRoomData(this.client, room, roomData); this.processRoomData(this.client, room, roomData);
} }
private onLifecycle(state: SlidingSyncState, resp: MSC3575SlidingSyncResponse, err?: Error): void { private onLifecycle(state: SlidingSyncState, resp: MSC3575SlidingSyncResponse | null, err: Error | null): void {
if (err) { if (err) {
logger.debug("onLifecycle", state, err); logger.debug("onLifecycle", state, err);
} }
switch (state) { switch (state) {
case SlidingSyncState.Complete: case SlidingSyncState.Complete:
this.purgeNotifications(); this.purgeNotifications();
if (!resp) {
break;
}
// Element won't stop showing the initial loading spinner unless we fire SyncState.Prepared // Element won't stop showing the initial loading spinner unless we fire SyncState.Prepared
if (!this.lastPos) { if (!this.lastPos) {
this.updateSyncState(SyncState.Prepared, { this.updateSyncState(SyncState.Prepared, {
@@ -472,6 +475,13 @@ export class SlidingSyncSdk {
} }
} }
if (Number.isInteger(roomData.invited_count)) {
room.currentState.setInvitedMemberCount(roomData.invited_count!);
}
if (Number.isInteger(roomData.joined_count)) {
room.currentState.setJoinedMemberCount(roomData.joined_count!);
}
if (roomData.invite_state) { if (roomData.invite_state) {
const inviteStateEvents = mapEvents(this.client, room.roomId, roomData.invite_state); const inviteStateEvents = mapEvents(this.client, room.roomId, roomData.invite_state);
this.processRoomEvents(room, inviteStateEvents); this.processRoomEvents(room, inviteStateEvents);

View File

@@ -84,6 +84,8 @@ export interface MSC3575RoomData {
timeline: (IRoomEvent | IStateEvent)[]; timeline: (IRoomEvent | IStateEvent)[];
notification_count?: number; notification_count?: number;
highlight_count?: number; highlight_count?: number;
joined_count?: number;
invited_count?: number;
invite_state?: IStateEvent[]; invite_state?: IStateEvent[];
initial?: boolean; initial?: boolean;
limited?: boolean; limited?: boolean;
@@ -320,7 +322,9 @@ export enum SlidingSyncEvent {
export type SlidingSyncEventHandlerMap = { export type SlidingSyncEventHandlerMap = {
[SlidingSyncEvent.RoomData]: (roomId: string, roomData: MSC3575RoomData) => void; [SlidingSyncEvent.RoomData]: (roomId: string, roomData: MSC3575RoomData) => void;
[SlidingSyncEvent.Lifecycle]: (state: SlidingSyncState, resp: MSC3575SlidingSyncResponse, err: Error) => void; [SlidingSyncEvent.Lifecycle]: (
state: SlidingSyncState, resp: MSC3575SlidingSyncResponse | null, err: Error | null,
) => void;
[SlidingSyncEvent.List]: ( [SlidingSyncEvent.List]: (
listIndex: number, joinedCount: number, roomIndexToRoomId: Record<number, string>, listIndex: number, joinedCount: number, roomIndexToRoomId: Record<number, string>,
) => void; ) => void;