Last Owner should edit admins, and not leave when is last (#4372)

This commit is contained in:
Mauro
2025-08-07 10:40:14 +02:00
committed by GitHub
parent be525e6a60
commit 5ab6f90863
67 changed files with 691 additions and 363 deletions
@@ -9,15 +9,15 @@ import Foundation
import MatrixRustSDK
struct RoomPermissionsSetting: Identifiable {
var id: KeyPath<RoomPermissions, RoomMemberDetails.Role> { keyPath }
var id: KeyPath<RoomPermissions, RoomRole> { keyPath }
/// The title of this setting.
let title: String
/// The selected role of this setting.
var value: RoomMemberDetails.Role
var value: RoomRole
/// All of the available roles that this setting can be configured with.
var allValues: [(title: String, tag: RoomMemberDetails.Role)] {
var allValues: [(title: String, tag: RoomRole)] {
[
(title: L10n.screenRoomChangePermissionsAdministrators, tag: .administrator),
(title: L10n.screenRoomChangePermissionsModerators, tag: .moderator),
@@ -26,7 +26,7 @@ struct RoomPermissionsSetting: Identifiable {
}
/// The `RoomPermissions` property that this setting is for.
let keyPath: KeyPath<RoomPermissions, RoomMemberDetails.Role>
let keyPath: KeyPath<RoomPermissions, RoomRole>
/// The `RoomPowerLevelChanges` property that this setting is saved into.
var rustKeyPath: WritableKeyPath<RoomPowerLevelChanges, Int64?> {
switch keyPath {
@@ -47,99 +47,39 @@ struct RoomPermissionsSetting: Identifiable {
struct RoomPermissions {
/// The level required to ban a user.
var ban: RoomMemberDetails.Role
var ban: RoomRole
/// The level required to invite a user.
var invite: RoomMemberDetails.Role
var invite: RoomRole
/// The level required to kick a user.
var kick: RoomMemberDetails.Role
var kick: RoomRole
/// The level required to redact an event.
var redact: RoomMemberDetails.Role
var redact: RoomRole
/// The default level required to send message events.
var eventsDefault: RoomMemberDetails.Role
var eventsDefault: RoomRole
/// The default level required to send state events.
var stateDefault: RoomMemberDetails.Role
var stateDefault: RoomRole
/// The default power level for every user in the room.
var usersDefault: RoomMemberDetails.Role
var usersDefault: RoomRole
/// The level required to change the room's name.
var roomName: RoomMemberDetails.Role
var roomName: RoomRole
/// The level required to change the room's avatar.
var roomAvatar: RoomMemberDetails.Role
var roomAvatar: RoomRole
/// The level required to change the room's topic.
var roomTopic: RoomMemberDetails.Role
var roomTopic: RoomRole
}
extension RoomPermissions {
/// Create permissions from the room's power levels.
init(powerLevels: RoomPowerLevelsValues) {
ban = RoomMemberDetails.Role(powerLevelValue: powerLevels.ban)
invite = RoomMemberDetails.Role(powerLevelValue: powerLevels.invite)
kick = RoomMemberDetails.Role(powerLevelValue: powerLevels.kick)
redact = RoomMemberDetails.Role(powerLevelValue: powerLevels.redact)
eventsDefault = RoomMemberDetails.Role(powerLevelValue: powerLevels.eventsDefault)
stateDefault = RoomMemberDetails.Role(powerLevelValue: powerLevels.stateDefault)
usersDefault = RoomMemberDetails.Role(powerLevelValue: powerLevels.usersDefault)
roomName = RoomMemberDetails.Role(powerLevelValue: powerLevels.roomName)
roomAvatar = RoomMemberDetails.Role(powerLevelValue: powerLevels.roomAvatar)
roomTopic = RoomMemberDetails.Role(powerLevelValue: powerLevels.roomTopic)
}
}
extension RoomMemberDetails.Role {
init(powerLevelValue: Int64) {
// Also this is not great, and should be handled by a `suggestedRoleForPowerLevelValue` function from the SDK
guard powerLevelValue < 150 else {
self = .owner
return
}
do {
switch try suggestedRoleForPowerLevel(powerLevel: .value(value: powerLevelValue)) {
case .administrator:
self = .administrator
case .creator:
fatalError("Impossible")
case .moderator:
self = .moderator
case .user:
self = .user
}
} catch {
MXLog.error("Falied to convert power level value to role: \(error)")
self = .user
}
}
var rustRole: RoomMemberRole {
switch self {
case .creator:
.creator
case .administrator, .owner:
.administrator
case .moderator:
.moderator
case .user:
.user
}
}
/// To be used when setting the power level of a user to get the suggested equivalent power level value for that specific role
/// NOTE: Do not use for comparison, use the true power level instead.
var powerLevelValue: Int64 {
guard self != .owner else {
// Would be better if the SDK would return this, maybe a `suggestedPowerLevelValueForRole` function would solve the problem
return 150
}
do {
switch try suggestedPowerLevelForRole(role: rustRole) {
case .infinite:
fatalError("Impossible")
case .value(let value):
return value
}
} catch {
MXLog.error("Falied to convert role to power level value: \(error)")
return 0
}
ban = RoomRole(powerLevelValue: powerLevels.ban)
invite = RoomRole(powerLevelValue: powerLevels.invite)
kick = RoomRole(powerLevelValue: powerLevels.kick)
redact = RoomRole(powerLevelValue: powerLevels.redact)
eventsDefault = RoomRole(powerLevelValue: powerLevels.eventsDefault)
stateDefault = RoomRole(powerLevelValue: powerLevels.stateDefault)
usersDefault = RoomRole(powerLevelValue: powerLevels.usersDefault)
roomName = RoomRole(powerLevelValue: powerLevels.roomName)
roomAvatar = RoomRole(powerLevelValue: powerLevels.roomAvatar)
roomTopic = RoomRole(powerLevelValue: powerLevels.roomTopic)
}
}