diff --git a/src/components/views/elements/PowerSelector.tsx b/src/components/views/elements/PowerSelector.tsx index 6c7c1889d4..fd74fa482f 100644 --- a/src/components/views/elements/PowerSelector.tsx +++ b/src/components/views/elements/PowerSelector.tsx @@ -14,6 +14,7 @@ import Field from "./Field"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { objectHasDiff } from "../../../utils/objects"; +import { arrayHasDiff } from "../../../utils/arrays.ts"; const CUSTOM_VALUE = "SELECT_VALUE_CUSTOM"; @@ -38,7 +39,6 @@ interface Props { } interface IState { - levelRoleMap: Partial>; // List of power levels to show in the drop-down options: number[]; @@ -47,7 +47,7 @@ interface IState { custom?: boolean; } -export default class PowerSelector extends React.Component, IState> { +export default class PowerSelector extends React.PureComponent, IState> { public static defaultProps: Partial> = { maxValue: Infinity, usersDefault: 0, @@ -58,7 +58,6 @@ export default class PowerSelector extends React.C super(props); this.state = { - levelRoleMap: {}, // List of power levels to show in the drop-down options: [], @@ -85,6 +84,7 @@ export default class PowerSelector extends React.C private initStateFromProps(): void { // This needs to be done now because levelRoleMap has translated strings const levelRoleMap = Roles.levelRoleMap(this.props.usersDefault); + const options = Object.keys(levelRoleMap) .filter((level) => { return ( @@ -93,11 +93,13 @@ export default class PowerSelector extends React.C }) .map((level) => parseInt(level)); + if (arrayHasDiff(options, this.state.options)) { + this.setState({ options }); + } + const isCustom = levelRoleMap[this.props.value] === undefined; this.setState({ - levelRoleMap, - options, custom: isCustom, customValue: this.props.value, selectValue: isCustom ? CUSTOM_VALUE : this.props.value, diff --git a/src/components/views/settings/PowerLevelSelector.tsx b/src/components/views/settings/PowerLevelSelector.tsx index 0b570c1516..875aa5c999 100644 --- a/src/components/views/settings/PowerLevelSelector.tsx +++ b/src/components/views/settings/PowerLevelSelector.tsx @@ -32,7 +32,7 @@ interface PowerLevelSelectorProps { */ canChangeLevels: boolean; /** - * The current user power level + * The current user's own power level */ currentUserLevel: number; /** @@ -105,6 +105,7 @@ export function PowerLevelSelector({ disabled={!canChange} label={userId} key={userId} + maxValue={currentUserLevel} onChange={async (value) => { const userLevelsTmp = Object.assign({}, userLevels); userLevelsTmp[userId] = value; diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index 308918e1b3..c9078d86e3 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -26,6 +26,7 @@ import { SettingsSection } from "../../shared/SettingsSection"; import MatrixClientContext from "../../../../../contexts/MatrixClientContext"; import { PowerLevelSelector } from "../../PowerLevelSelector"; import { ElementCallEventType, ElementCallMemberEventType } from "../../../../../call-types"; +import { objectClone } from "../../../../../utils/objects.ts"; interface IEventShowOpts { isState?: boolean; @@ -221,12 +222,9 @@ export default class RolesRoomSettingsTab extends React.Component() ?? {}; - // Clone the power levels just in case - plContent = Object.assign({}, plContent); - - // powerLevelKey should be a user ID - if (!plContent["users"]) plContent["users"] = {}; - plContent["users"][powerLevelKey] = value; + // Clone the power levels so we can modify it without clobbering the js-sdk + plContent = objectClone({ users: {}, ...plContent }); + plContent["users"]![powerLevelKey] = value; try { await client.sendStateEvent(this.props.room.roomId, EventType.RoomPowerLevels, plContent); diff --git a/test/unit-tests/components/views/settings/tabs/room/RolesRoomSettingsTab-test.tsx b/test/unit-tests/components/views/settings/tabs/room/RolesRoomSettingsTab-test.tsx index 44ec287862..42538204cb 100644 --- a/test/unit-tests/components/views/settings/tabs/room/RolesRoomSettingsTab-test.tsx +++ b/test/unit-tests/components/views/settings/tabs/room/RolesRoomSettingsTab-test.tsx @@ -233,6 +233,7 @@ describe("RolesRoomSettingsTab", () => { return null; }); mocked(room.currentState.mayClientSendStateEvent).mockReturnValue(true); + mocked(room.getMember).mockReturnValue({ powerLevel: 100 } as any); const { container } = await renderTab(); const selector = container.querySelector(`[placeholder="${cli.getUserId()}"]`)!;