Restore permissions to creator and display them as owners in the list (#4369)

* restore permissions to creator and display them as owners in the list

* improved the code to use actually 5 roles in the app to distinguish a real creator from an owner
This commit is contained in:
Mauro
2025-07-31 16:52:55 +02:00
committed by GitHub
parent 496c29ae36
commit 731d60b6e9
29 changed files with 205 additions and 137 deletions
@@ -19,7 +19,19 @@ struct RoomMemberDetails: Identifiable, Hashable {
var isBanned: Bool
var isActive: Bool
enum Role { case administrator, moderator, user }
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 powerLevel: RoomPowerLevel
@@ -39,18 +51,47 @@ extension RoomMemberDetails {
isInvited = proxy.membership == .invite
isIgnored = proxy.isIgnored
isBanned = proxy.membership == .ban
role = .init(proxy.role)
role = .init(proxy.role, powerLevel: proxy.powerLevel)
powerLevel = proxy.powerLevel
}
}
extension RoomMemberDetails.Role {
init(_ role: RoomMemberRole) {
self = switch role {
// TODO: Implement creator role
case .creator, .administrator: .administrator
case .moderator: .moderator
case .user: .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
}
}
}
extension RoomMemberRole {
var isAdminOrHigher: Bool {
switch self {
case .administrator, .creator:
return true
case .moderator, .user:
return false
}
}
}
@@ -86,17 +86,34 @@ extension RoomPermissions {
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 {
try self.init(suggestedRoleForPowerLevel(powerLevel: .value(value: powerLevelValue)))
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.init(.user)
self = .user
}
}
var rustRole: RoomMemberRole {
switch self {
case .administrator:
case .creator:
.creator
case .administrator, .owner:
.administrator
case .moderator:
.moderator
@@ -108,11 +125,15 @@ extension RoomMemberDetails.Role {
/// 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:
// Would be better if the SDK would return this, maybe a `suggestedPowerLevelValueForRole` function would solve the problem
return 150
fatalError("Impossible")
case .value(let value):
return value
}
@@ -11,9 +11,7 @@ import MatrixRustSDK
protocol RoomPowerLevelsProxyProtocol {
var values: RoomPowerLevelsValues { get }
var userPowerLevels: [String: Int64] { get }
func suggestedRole(forUser userID: String) -> RoomMemberRole
func canOwnUser(sendMessage messageType: MessageLikeEventType) -> Bool
func canOwnUser(sendStateEvent event: StateEventType) -> Bool
func canOwnUserInvite() -> Bool
@@ -24,6 +22,7 @@ protocol RoomPowerLevelsProxyProtocol {
func canOwnUserTriggerRoomNotification() -> Bool
func canOwnUserPinOrUnpin() -> Bool
func canOwnUserJoinCall() -> Bool
func canOwnUserEditRolesAndPermissions() -> Bool
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError>
func canUser(userID: String, sendStateEvent event: StateEventType) -> Result<Bool, RoomProxyError>
@@ -26,16 +26,6 @@ struct RoomPowerLevelsProxy: RoomPowerLevelsProxyProtocol {
powerLevels.userPowerLevels()
}
func suggestedRole(forUser userID: String) -> RoomMemberRole {
do {
let powerLevelValue = powerLevels.userPowerLevels()[userID] ?? values.usersDefault
return try suggestedRoleForPowerLevel(powerLevel: .value(value: powerLevelValue))
} catch {
MXLog.error("Falied to get suggested role for user: \(error)")
return .user
}
}
func canOwnUser(sendMessage messageType: MessageLikeEventType) -> Bool {
powerLevels.canOwnUserSendMessage(message: messageType)
}
@@ -76,6 +66,10 @@ struct RoomPowerLevelsProxy: RoomPowerLevelsProxyProtocol {
powerLevels.canOwnUserSendState(stateEvent: .callMember)
}
func canOwnUserEditRolesAndPermissions() -> Bool {
powerLevels.canOwnUserSendState(stateEvent: .roomPowerLevels)
}
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError> {
do {
return try .success(powerLevels.canUserSendMessage(userId: userID, message: messageType))