Update the member list invite button when power levels change (#34475)

canInvite was only recomputed on third party invite state events, so granting or
revoking the power to invite left the member list header button in its previous
enabled or disabled state until the list was reopened.

Recompute it on RoomStateEvent.Update as well, which also covers the space join
rule branch in canInviteTo(), matching RoomSummaryCardViewModel.

Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
hayyaksi
2026-08-11 16:02:37 +00:00
committed by GitHub
co-authored by Michael Telatynski
parent 0a86a6b93d
commit f37623f054
2 changed files with 27 additions and 2 deletions
@@ -218,7 +218,12 @@ export function useMemberListViewModel(roomId: string): MemberListViewState {
});
useTypedEventEmitter(cli, RoomStateEvent.Update, (state: RoomState) => {
if (state.roomId === roomId) loadMembers();
if (state.roomId === roomId) {
loadMembers();
// Power level and join rule changes both surface here, and both can change whether we may
// invite. Mirrors RoomSummaryCardViewModel, which recomputes canInviteTo on the same event.
setCanInvite(getCanUserInviteToThisRoom());
}
});
useTypedEventEmitter(cli, RoomMemberEvent.Name, (_: MatrixEvent, member: SdkRoomMember) => {
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
*/
import { act, fireEvent, screen, waitFor } from "jest-matrix-react";
import { RoomMember, User, RoomEvent } from "matrix-js-sdk/src/matrix";
import { RoomMember, User, RoomEvent, RoomStateEvent, type RoomState } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { mocked } from "jest-mock";
@@ -99,6 +99,26 @@ describe("MemberListHeaderView", () => {
);
});
it("Updates the invite button when a power level change grants invite rights", async () => {
const { memberListRoom, client, reRender } = rendered;
jest.spyOn(memberListRoom, "getMyMembership").mockReturnValue(KnownMembership.Join);
jest.spyOn(memberListRoom, "canInvite").mockReturnValue(false);
await reRender();
await waitFor(() =>
expect(screen.getByRole("button", { name: "Invite" })).toHaveAttribute("aria-disabled", "true"),
);
// Grant the right to invite, and announce it the way a power level change does
jest.spyOn(memberListRoom, "canInvite").mockReturnValue(true);
act(() => {
client.emit(RoomStateEvent.Update, { roomId: memberListRoom.roomId } as RoomState);
});
await waitFor(() =>
expect(screen.getByRole("button", { name: "Invite" })).not.toHaveAttribute("aria-disabled", "true"),
);
});
it("Opens room inviter on button click", async () => {
const { memberListRoom, reRender } = rendered;
jest.spyOn(defaultDispatcher, "dispatch");