mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Last Owner should edit admins, and not leave when is last (#4372)
This commit is contained in:
@@ -211,7 +211,7 @@ extension AnalyticsService {
|
||||
}
|
||||
|
||||
/// Track a room moderation action.
|
||||
func trackRoomModeration(action: AnalyticsEvent.RoomModeration.Action, role: RoomMemberDetails.Role?) {
|
||||
func trackRoomModeration(action: AnalyticsEvent.RoomModeration.Action, role: RoomRole?) {
|
||||
let role = role.map(AnalyticsEvent.RoomModeration.Role.init)
|
||||
capture(event: AnalyticsEvent.RoomModeration(action: action, role: role))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import AnalyticsEvents
|
||||
|
||||
extension AnalyticsEvent.RoomModeration.Role {
|
||||
init(role: RoomMemberDetails.Role) {
|
||||
init(role: RoomRole) {
|
||||
switch role {
|
||||
case .administrator, .creator, .owner:
|
||||
// This probably needs to be updates
|
||||
|
||||
@@ -18,21 +18,8 @@ struct RoomMemberDetails: Identifiable, Hashable {
|
||||
var isIgnored: Bool
|
||||
var isBanned: Bool
|
||||
var isActive: Bool
|
||||
|
||||
enum Role {
|
||||
/// Creator of the room, PL infinite
|
||||
case creator
|
||||
/// Same power of an admin, but they can also upgrade the room, PL 150 onwards
|
||||
case owner
|
||||
/// Able to edit room settings and perform any action aside from room upgrading PL 100...149
|
||||
case administrator
|
||||
/// Able to perform room moderation actions PL 50...99
|
||||
case moderator
|
||||
/// Default role PL 0...49
|
||||
case user
|
||||
}
|
||||
|
||||
let role: Role
|
||||
let role: RoomRole
|
||||
let powerLevel: RoomPowerLevel
|
||||
|
||||
func matches(searchQuery: String) -> Bool {
|
||||
@@ -51,47 +38,7 @@ extension RoomMemberDetails {
|
||||
isInvited = proxy.membership == .invite
|
||||
isIgnored = proxy.isIgnored
|
||||
isBanned = proxy.membership == .ban
|
||||
role = .init(proxy.role, powerLevel: proxy.powerLevel)
|
||||
role = proxy.role
|
||||
powerLevel = proxy.powerLevel
|
||||
}
|
||||
}
|
||||
|
||||
extension RoomMemberDetails.Role {
|
||||
init(_ role: RoomMemberRole, powerLevel: RoomPowerLevel) {
|
||||
switch role {
|
||||
case .creator:
|
||||
self = .creator
|
||||
case .administrator:
|
||||
switch powerLevel {
|
||||
case .value(let value):
|
||||
self = value >= 150 ? .owner : .administrator
|
||||
default:
|
||||
fatalError("Impossible")
|
||||
}
|
||||
case .moderator:
|
||||
self = .moderator
|
||||
case .user:
|
||||
self = .user
|
||||
}
|
||||
}
|
||||
|
||||
var isAdminOrHigher: Bool {
|
||||
switch self {
|
||||
case .administrator, .creator, .owner:
|
||||
return true
|
||||
case .moderator, .user:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension RoomMemberRole {
|
||||
var isAdminOrHigher: Bool {
|
||||
switch self {
|
||||
case .administrator, .creator:
|
||||
return true
|
||||
case .moderator, .user:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,4 @@ final class RoomMemberProxy: RoomMemberProxyProtocol {
|
||||
var isIgnored: Bool { member.isIgnored }
|
||||
|
||||
var powerLevel: RoomPowerLevel { .init(rustPowerLevel: member.powerLevel) }
|
||||
|
||||
var role: RoomMemberRole { member.suggestedRoleForPowerLevel }
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ protocol RoomMemberProxyProtocol: AnyObject {
|
||||
var isIgnored: Bool { get }
|
||||
|
||||
var powerLevel: RoomPowerLevel { get }
|
||||
|
||||
var role: RoomMemberRole { get }
|
||||
}
|
||||
|
||||
extension RoomMemberProxyProtocol {
|
||||
@@ -58,3 +56,7 @@ extension [RoomMemberProxyProtocol] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension RoomMemberProxyProtocol {
|
||||
var role: RoomRole { .init(powerLevel: powerLevel) }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import MatrixRustSDK
|
||||
|
||||
enum RoomRole: Comparable {
|
||||
/// Default role PL 0...49
|
||||
case user
|
||||
/// Able to perform room moderation actions PL 50...99
|
||||
case moderator
|
||||
/// Able to edit room settings and perform any action aside from room upgrading PL 100...149
|
||||
case administrator
|
||||
/// Same power of an admin, but they can also upgrade the room, PL 150 onwards
|
||||
case owner
|
||||
/// Creator of the room, PL infinite
|
||||
case creator
|
||||
}
|
||||
|
||||
extension RoomRole {
|
||||
init(powerLevel: RoomPowerLevel) {
|
||||
do {
|
||||
let role = try suggestedRoleForPowerLevel(powerLevel: powerLevel.rustPowerLevel)
|
||||
self.init(role, powerLevel: powerLevel)
|
||||
} catch {
|
||||
MXLog.error("Failled to get suggested role for power level \(powerLevel): \(error)")
|
||||
self = .user
|
||||
}
|
||||
}
|
||||
|
||||
init(_ role: RoomMemberRole, powerLevel: RoomPowerLevel) {
|
||||
switch role {
|
||||
case .creator:
|
||||
self = .creator
|
||||
case .administrator:
|
||||
switch powerLevel {
|
||||
case .value(let value):
|
||||
self = value >= 150 ? .owner : .administrator
|
||||
default:
|
||||
fatalError("Impossible")
|
||||
}
|
||||
case .moderator:
|
||||
self = .moderator
|
||||
case .user:
|
||||
self = .user
|
||||
}
|
||||
}
|
||||
|
||||
var isAdminOrHigher: Bool {
|
||||
switch self {
|
||||
case .administrator, .creator, .owner:
|
||||
return true
|
||||
case .moderator, .user:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var isOwner: Bool {
|
||||
switch self {
|
||||
case .creator, .owner:
|
||||
return true
|
||||
case .administrator, .moderator, .user:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension RoomRole {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user