Fix room settings roles tab getting confused if power level change fails (#31768)

* Fix room settings roles tab getting confused if power level change fails

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2026-01-19 12:08:42 +00:00 committed by GitHub
parent 3f021472c2
commit b8ad0b93db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 14 additions and 12 deletions

View File

@ -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<K extends undefined | string> {
}
interface IState {
levelRoleMap: Partial<Record<number | "undefined", string>>;
// List of power levels to show in the drop-down
options: number[];
@ -47,7 +47,7 @@ interface IState {
custom?: boolean;
}
export default class PowerSelector<K extends undefined | string> extends React.Component<Props<K>, IState> {
export default class PowerSelector<K extends undefined | string> extends React.PureComponent<Props<K>, IState> {
public static defaultProps: Partial<Props<any>> = {
maxValue: Infinity,
usersDefault: 0,
@ -58,7 +58,6 @@ export default class PowerSelector<K extends undefined | string> 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<K extends undefined | string> 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<K extends undefined | string> 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,

View File

@ -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;

View File

@ -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<IProps, RolesR
const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, "");
let plContent = plEvent?.getContent<RoomPowerLevelsEventContent>() ?? {};
// 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);

View File

@ -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()}"]`)!;