Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix automatic DM avatar with functional members #4017

Merged
merged 22 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0ce2d82
fix automatic DM avatar with functional members
HarHarLinks Jan 19, 2024
f9b41f6
update comments
HarHarLinks Feb 6, 2024
e65fb24
lint
HarHarLinks Feb 6, 2024
c114bf5
add tests for functional members
HarHarLinks Feb 6, 2024
92aef67
Merge branch 'develop' into fix-functional-members-avatar
richvdh Feb 26, 2024
25fdc18
keep functional members out of the public API
HarHarLinks Feb 26, 2024
d6f83d3
filter functional members from more candidates
HarHarLinks Feb 26, 2024
657f1bc
add tests for fallback avatars with functional members
HarHarLinks Feb 26, 2024
9234e82
Merge branch 'develop' into fix-functional-members-avatar
HarHarLinks Feb 26, 2024
5794809
Add docstring for getFunctionalMembers
HarHarLinks Feb 28, 2024
0789a23
inline getInvitedAndJoinedFunctionalMemberCount
HarHarLinks Feb 28, 2024
b2b5b18
update comments for getAvatarFallbackMember
HarHarLinks Feb 28, 2024
fa4666c
use correct list of heroes in getAvatarFallbackMember
HarHarLinks Feb 28, 2024
404d671
remove redundant type annotation
HarHarLinks Feb 28, 2024
0f6ab78
optimize performance of invitedAndJoinedFunctionalMemberCount
HarHarLinks Feb 28, 2024
8db6b47
calculate nonFunctionalMemberCount in one step
HarHarLinks Feb 28, 2024
66157c4
clean up functional member tests with review feedback
HarHarLinks Feb 28, 2024
684dcac
lint
HarHarLinks Feb 28, 2024
0ea0d50
Update src/models/room.ts
HarHarLinks Mar 12, 2024
efca7ba
apply feedback about comments
HarHarLinks Mar 12, 2024
882f625
non-functional per review, lint
HarHarLinks Mar 12, 2024
5f8a985
Merge branch 'develop' into fix-functional-members-avatar
HarHarLinks Mar 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 111 additions & 1 deletion spec/unit/room-state.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ import { makeBeaconEvent, makeBeaconInfoEvent } from "../test-utils/beacon";
import { filterEmitCallsByEventType } from "../test-utils/emitter";
import { RoomState, RoomStateEvent } from "../../src/models/room-state";
import { Beacon, BeaconEvent, getBeaconInfoIdentifier } from "../../src/models/beacon";
import { EventType, RelationType, UNSTABLE_MSC2716_MARKER } from "../../src/@types/event";
import {
EventType,
RelationType,
UNSTABLE_ELEMENT_FUNCTIONAL_USERS,
UNSTABLE_MSC2716_MARKER,
} from "../../src/@types/event";
import { MatrixEvent, MatrixEventEvent } from "../../src/models/event";
import { M_BEACON } from "../../src/@types/beacon";
import { MatrixClient } from "../../src/client";
Expand Down Expand Up @@ -704,6 +709,59 @@ describe("RoomState", function () {
});
});

describe("getJoinedFunctionalMemberCount", function () {
beforeEach(() => {
state = new RoomState(roomId);
});

it("should update after adding joined functional member", function () {
state.setStateEvents([
utils.mkMembership({ event: true, mship: "join", user: userA, room: roomId }),
utils.mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.unstable!,
skey: "",
sender: userB,
room: roomId,
content: { service_members: [userA] },
}),
]);
expect(state.getJoinedMemberCount()).toEqual(1);
expect(state.getJoinedFunctionalMemberCount()).toEqual(1);
state.setStateEvents([
utils.mkMembership({ event: true, mship: "join", user: userC, room: roomId }),
utils.mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.unstable!,
skey: "",
sender: userB,
room: roomId,
content: { service_members: [userA, userC] },
}),
]);
expect(state.getJoinedMemberCount()).toEqual(2);
expect(state.getJoinedFunctionalMemberCount()).toEqual(2);
});

it("should not update after adding joined non-functional member", function () {
state.setStateEvents([utils.mkMembership({ event: true, mship: "join", user: userA, room: roomId })]);
expect(state.getJoinedMemberCount()).toEqual(1);
expect(state.getJoinedFunctionalMemberCount()).toEqual(0);
state.setStateEvents([
utils.mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.unstable!,
skey: "",
sender: userB,
room: roomId,
content: { service_members: [userA] },
}),
]);
expect(state.getJoinedMemberCount()).toEqual(1);
expect(state.getJoinedFunctionalMemberCount()).toEqual(1);
});
});

describe("getInvitedMemberCount", function () {
beforeEach(() => {
state = new RoomState(roomId);
Expand All @@ -717,6 +775,58 @@ describe("RoomState", function () {
});
});

describe("getInvitedFunctionalMemberCount", function () {
beforeEach(() => {
state = new RoomState(roomId);
});
it("should update after adding invited functional member", function () {
state.setStateEvents([
utils.mkMembership({ event: true, mship: "invite", user: userA, room: roomId }),
utils.mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.unstable!,
skey: "",
sender: userB,
room: roomId,
content: { service_members: [userA] },
}),
]);
expect(state.getInvitedMemberCount()).toEqual(1);
expect(state.getInvitedFunctionalMemberCount()).toEqual(1);
state.setStateEvents([
utils.mkMembership({ event: true, mship: "invite", user: userC, room: roomId }),
utils.mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.unstable!,
skey: "",
sender: userB,
room: roomId,
content: { service_members: [userA, userC] },
}),
]);
expect(state.getInvitedMemberCount()).toEqual(2);
expect(state.getInvitedFunctionalMemberCount()).toEqual(2);
});

it("should not update after adding invited non-functional member", function () {
state.setStateEvents([utils.mkMembership({ event: true, mship: "invite", user: userA, room: roomId })]);
expect(state.getInvitedMemberCount()).toEqual(1);
expect(state.getInvitedFunctionalMemberCount()).toEqual(0);
state.setStateEvents([
utils.mkEvent({
event: true,
type: UNSTABLE_ELEMENT_FUNCTIONAL_USERS.unstable!,
skey: "",
sender: userB,
room: roomId,
content: { service_members: [userA] },
}),
]);
expect(state.getInvitedMemberCount()).toEqual(1);
expect(state.getInvitedFunctionalMemberCount()).toEqual(1);
});
});

describe("setJoinedMemberCount", function () {
beforeEach(() => {
state = new RoomState(roomId);
Expand Down
35 changes: 35 additions & 0 deletions src/models/room-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { TypedEventEmitter } from "./typed-event-emitter";
import { Beacon, BeaconEvent, BeaconEventHandlerMap, getBeaconInfoIdentifier, BeaconIdentifier } from "./beacon";
import { TypedReEmitter } from "../ReEmitter";
import { M_BEACON, M_BEACON_INFO } from "../@types/beacon";
import { UNSTABLE_ELEMENT_FUNCTIONAL_USERS } from "../@types/event";

export interface IMarkerFoundOptions {
/** Whether the timeline was empty before the marker event arrived in the
Expand Down Expand Up @@ -220,6 +221,16 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
this.summaryJoinedMemberCount = count;
}

/**
* Returns the number of joined functional members in this room
* @returns The number of functional members in this room whose membership is 'join'
*/
public getJoinedFunctionalMemberCount(): number {
return this.getFunctionalMembers().reduce((count, m) => {
return this.getMembers().find((member) => member.userId === m)?.membership === "join" ? count + 1 : count;
}, 0);
}

/**
* Returns the number of invited members in this room
* @returns The number of members in this room whose membership is 'invite'
Expand All @@ -236,6 +247,16 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
return this.invitedMemberCount;
}

/**
* Returns the number of invited functional members in this room
* @returns The number of functional members in this room whose membership is 'invite'
*/
public getInvitedFunctionalMemberCount(): number {
return this.getFunctionalMembers().reduce((count, m) => {
return this.getMembers().find((member) => member.userId === m)?.membership === "invite" ? count + 1 : count;
}, 0);
}

/**
* Set the amount of invited members in this room
* @param count - the amount of invited members
Expand All @@ -252,6 +273,20 @@ export class RoomState extends TypedEventEmitter<EmittedEvents, EventHandlerMap>
return Object.values(this.members);
}

/**
* Get all functional members in this room.
* @returns A list of MXID Strings.
*/
public getFunctionalMembers(): String[] {
const [functionalUsersStateEvent] = this.getStateEvents(UNSTABLE_ELEMENT_FUNCTIONAL_USERS.name);

if (Array.isArray(functionalUsersStateEvent?.getContent().service_members)) {
return functionalUsersStateEvent.getContent().service_members;
}

return [];
}

/**
* Get all RoomMembers in this room, excluding the user IDs provided.
* @param excludedIds - The user IDs to exclude.
Expand Down
29 changes: 28 additions & 1 deletion src/models/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
}

public getAvatarFallbackMember(): RoomMember | undefined {
const memberCount = this.getInvitedAndJoinedMemberCount();
const memberCount = this.getInvitedAndJoinedMemberCount() - this.getInvitedAndJoinedFunctionalMemberCount();
HarHarLinks marked this conversation as resolved.
Show resolved Hide resolved
if (memberCount > 2) {
return;
}
Expand Down Expand Up @@ -1699,6 +1699,25 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
return this.currentState.getInvitedMemberCount();
}

/**
* Returns the number of joined non-functional members in this room
* This method caches the result.
* This is a wrapper around the method of the same name in roomState, returning
* its result for the room's current state.
* @returns The number of non-functional members in this room whose membership is 'join'
*/
public getJoinedFunctionalMemberCount(): number {
return this.currentState.getJoinedFunctionalMemberCount();
}

/**
* Returns the number of non-functional invited members in this room
* @returns The number of non-functional members in this room whose membership is 'invite'
*/
public getInvitedFunctionalMemberCount(): number {
return this.currentState.getInvitedFunctionalMemberCount();
}

/**
* Returns the number of invited + joined members in this room
* @returns The number of members in this room whose membership is 'invite' or 'join'
Expand All @@ -1707,6 +1726,14 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
return this.getInvitedMemberCount() + this.getJoinedMemberCount();
}

/**
* Returns the number of invited + joined non-functional members in this room
* @returns The number of non-functional members in this room whose membership is 'invite' or 'join'
*/
public getInvitedAndJoinedFunctionalMemberCount(): number {
return this.getInvitedFunctionalMemberCount() + this.getJoinedFunctionalMemberCount();
}

/**
* Get a list of members with given membership state.
* @param membership - The membership state.
Expand Down
Loading