implemented a way to filter out roles that can't be assigned to permission, and disable permissions that are above the current power level of the user.

This commit is contained in:
Mauro Romito
2025-12-18 18:43:19 +01:00
committed by Mauro
parent e95d0531fb
commit 3626f94289
18 changed files with 197 additions and 90 deletions

View File

@@ -119,10 +119,10 @@ class RoomRolesAndPermissionsFlowCoordinator: FlowCoordinatorProtocol {
stateMachine.addRoutes(event: .finishedChangingRoles, transitions: [.changingRoles => .rolesAndPermissionsScreen])
stateMachine.addRoutes(event: .changePermissions, transitions: [.rolesAndPermissionsScreen => .changingPermissions]) { [weak self] context in
guard let permissions = context.userInfo as? RoomPermissions else {
guard let (ownPowerLevel, permissions) = context.userInfo as? (RoomPowerLevel, RoomPermissions) else {
fatalError("Expected a group and the current permissions")
}
self?.presentChangePermissionsScreen(permissions: permissions)
self?.presentChangePermissionsScreen(ownPowerLevel: ownPowerLevel, permissions: permissions)
}
stateMachine.addRoutes(event: .finishedChangingPermissions, transitions: [.changingPermissions => .rolesAndPermissionsScreen])
@@ -144,8 +144,8 @@ class RoomRolesAndPermissionsFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .editRoles(let role):
stateMachine.tryEvent(.changeRoles, userInfo: role)
case .editPermissions(let permissions):
stateMachine.tryEvent(.changePermissions, userInfo: permissions)
case .editPermissions(let ownPowerLevel, let permissions):
stateMachine.tryEvent(.changePermissions, userInfo: (ownPowerLevel, permissions))
case .demotedOwnUser:
stateMachine.tryEvent(.demotedOwnUser)
}
@@ -179,8 +179,9 @@ class RoomRolesAndPermissionsFlowCoordinator: FlowCoordinatorProtocol {
}
}
private func presentChangePermissionsScreen(permissions: RoomPermissions) {
let parameters = RoomChangePermissionsScreenCoordinatorParameters(permissions: permissions,
private func presentChangePermissionsScreen(ownPowerLevel: RoomPowerLevel, permissions: RoomPermissions) {
let parameters = RoomChangePermissionsScreenCoordinatorParameters(ownPowerLevel: ownPowerLevel,
permissions: permissions,
roomProxy: roomProxy,
userIndicatorController: userIndicatorController,
analytics: analytics)

View File

@@ -10,6 +10,7 @@ import Combine
import SwiftUI
struct RoomChangePermissionsScreenCoordinatorParameters {
let ownPowerLevel: RoomPowerLevel
let permissions: RoomPermissions
let roomProxy: JoinedRoomProxyProtocol
let userIndicatorController: UserIndicatorControllerProtocol
@@ -21,7 +22,6 @@ enum RoomChangePermissionsScreenCoordinatorAction {
}
final class RoomChangePermissionsScreenCoordinator: CoordinatorProtocol {
private let parameters: RoomChangePermissionsScreenCoordinatorParameters
private var viewModel: RoomChangePermissionsScreenViewModelProtocol
private var cancellables = Set<AnyCancellable>()
@@ -31,9 +31,8 @@ final class RoomChangePermissionsScreenCoordinator: CoordinatorProtocol {
}
init(parameters: RoomChangePermissionsScreenCoordinatorParameters) {
self.parameters = parameters
viewModel = RoomChangePermissionsScreenViewModel(currentPermissions: parameters.permissions,
ownPowerLevel: parameters.ownPowerLevel,
roomProxy: parameters.roomProxy,
userIndicatorController: parameters.userIndicatorController,
analytics: parameters.analytics)

View File

@@ -69,7 +69,7 @@ extension RoomChangePermissionsScreenViewState {
/// - Parameters:
/// - currentPermissions: The current permissions for the room.
/// - isSpace: if the room is a space or a normal room.
init(currentPermissions: RoomPermissions, isSpace: Bool) {
init(ownPowerLevel: RoomPowerLevel, currentPermissions: RoomPermissions, isSpace: Bool) {
var settings = [RoomChangePermissionsScreenGroup: [RoomPermissionsSetting]]()
for group in RoomChangePermissionsScreenGroup.allCases {
switch group {
@@ -77,12 +77,15 @@ extension RoomChangePermissionsScreenViewState {
settings[group] = [
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRoomName,
value: currentPermissions.roomName,
ownPowerLevel: ownPowerLevel,
keyPath: \.roomName),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRoomAvatar,
value: currentPermissions.roomAvatar,
ownPowerLevel: ownPowerLevel,
keyPath: \.roomAvatar),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRoomTopic,
value: currentPermissions.roomTopic,
ownPowerLevel: ownPowerLevel,
keyPath: \.roomTopic)
]
@@ -90,12 +93,15 @@ extension RoomChangePermissionsScreenViewState {
settings[group] = [
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsInvitePeople,
value: currentPermissions.invite,
ownPowerLevel: ownPowerLevel,
keyPath: \.invite),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRemovePeople,
value: currentPermissions.kick,
ownPowerLevel: ownPowerLevel,
keyPath: \.kick),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsBanPeople,
value: currentPermissions.ban,
ownPowerLevel: ownPowerLevel,
keyPath: \.ban)
]
case .messagesAndContent:
@@ -103,9 +109,11 @@ extension RoomChangePermissionsScreenViewState {
settings[group] = [
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsSendMessages,
value: currentPermissions.eventsDefault,
ownPowerLevel: ownPowerLevel,
keyPath: \.eventsDefault),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsDeleteMessages,
value: currentPermissions.redact,
ownPowerLevel: ownPowerLevel,
keyPath: \.redact)
]
}
@@ -114,6 +122,7 @@ extension RoomChangePermissionsScreenViewState {
settings[group] = [
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsManageSpaceRooms,
value: currentPermissions.spaceChild,
ownPowerLevel: ownPowerLevel,
keyPath: \.spaceChild)
]
}

View File

@@ -23,13 +23,16 @@ class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModel
}
init(currentPermissions: RoomPermissions,
ownPowerLevel: RoomPowerLevel,
roomProxy: JoinedRoomProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol,
analytics: AnalyticsService) {
self.roomProxy = roomProxy
self.userIndicatorController = userIndicatorController
self.analytics = analytics
super.init(initialViewState: .init(currentPermissions: currentPermissions, isSpace: roomProxy.infoPublisher.value.isSpace))
super.init(initialViewState: .init(ownPowerLevel: ownPowerLevel,
currentPermissions: currentPermissions,
isSpace: roomProxy.infoPublisher.value.isSpace))
}
// MARK: - Public
@@ -64,7 +67,7 @@ class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModel
.flatMap { $0 }
.filter { state.currentPermissions[keyPath: $0.keyPath] != $0.value }
for setting in changedSettings {
changes[keyPath: setting.rustKeyPath] = setting.value.powerLevelValue
changes[keyPath: setting.rustKeyPath] = setting.value
}
switch await roomProxy.applyPowerLevelChanges(changes) {
@@ -106,14 +109,14 @@ class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModel
private func trackChanges(_ settings: [RoomPermissionsSetting]) {
for setting in settings {
switch setting.keyPath {
case \.ban: analytics.trackRoomModeration(action: .ChangePermissionsBanMembers, role: setting.value)
case \.invite: analytics.trackRoomModeration(action: .ChangePermissionsInviteUsers, role: setting.value)
case \.kick: analytics.trackRoomModeration(action: .ChangePermissionsKickMembers, role: setting.value)
case \.redact: analytics.trackRoomModeration(action: .ChangePermissionsRedactMessages, role: setting.value)
case \.eventsDefault: analytics.trackRoomModeration(action: .ChangePermissionsSendMessages, role: setting.value)
case \.roomName: analytics.trackRoomModeration(action: .ChangePermissionsRoomName, role: setting.value)
case \.roomAvatar: analytics.trackRoomModeration(action: .ChangePermissionsRoomAvatar, role: setting.value)
case \.roomTopic: analytics.trackRoomModeration(action: .ChangePermissionsRoomTopic, role: setting.value)
case \.ban: analytics.trackRoomModeration(action: .ChangePermissionsBanMembers, role: setting.roleValue)
case \.invite: analytics.trackRoomModeration(action: .ChangePermissionsInviteUsers, role: setting.roleValue)
case \.kick: analytics.trackRoomModeration(action: .ChangePermissionsKickMembers, role: setting.roleValue)
case \.redact: analytics.trackRoomModeration(action: .ChangePermissionsRedactMessages, role: setting.roleValue)
case \.eventsDefault: analytics.trackRoomModeration(action: .ChangePermissionsSendMessages, role: setting.roleValue)
case \.roomName: analytics.trackRoomModeration(action: .ChangePermissionsRoomName, role: setting.roleValue)
case \.roomAvatar: analytics.trackRoomModeration(action: .ChangePermissionsRoomAvatar, role: setting.roleValue)
case \.roomTopic: analytics.trackRoomModeration(action: .ChangePermissionsRoomTopic, role: setting.roleValue)
default: MXLog.warning("Unexpected change: \(setting.keyPath).")
}
}

View File

@@ -32,7 +32,9 @@ struct RoomChangePermissionsScreen: View {
Section {
ForEach(settings) { $setting in
ListRow(label: .plain(title: setting.title),
kind: .picker(selection: $setting.value, items: setting.allValues))
kind: .picker(selection: $setting.roleValue,
items: setting.availableValues))
.disabled(setting.isDisabled)
}
} header: {
Text(group.name)
@@ -64,6 +66,7 @@ struct RoomChangePermissionsScreen: View {
struct RoomChangePermissionsScreen_Previews: PreviewProvider, TestablePreview {
static let roomViewModel = makeViewModel(isSpace: false)
static let roomAsUserViewModel = makeViewModel(isSpace: false, ownPowerLevel: RoomRole.user.powerLevel)
static let spaceViewModel = makeViewModel(isSpace: true)
static var previews: some View {
@@ -72,14 +75,20 @@ struct RoomChangePermissionsScreen_Previews: PreviewProvider, TestablePreview {
}
.previewDisplayName("Room")
NavigationStack {
RoomChangePermissionsScreen(context: roomAsUserViewModel.context)
}
.previewDisplayName("Room as User")
NavigationStack {
RoomChangePermissionsScreen(context: spaceViewModel.context)
}
.previewDisplayName("Space")
}
static func makeViewModel(isSpace: Bool) -> RoomChangePermissionsScreenViewModel {
static func makeViewModel(isSpace: Bool, ownPowerLevel: RoomPowerLevel = RoomRole.creator.powerLevel) -> RoomChangePermissionsScreenViewModel {
RoomChangePermissionsScreenViewModel(currentPermissions: .init(powerLevels: .mock),
ownPowerLevel: ownPowerLevel,
roomProxy: JoinedRoomProxyMock(.init(isSpace: isSpace)),
userIndicatorController: UserIndicatorControllerMock(),
analytics: ServiceLocator.shared.analytics)

View File

@@ -17,7 +17,7 @@ struct RoomRolesAndPermissionsScreenCoordinatorParameters {
enum RoomRolesAndPermissionsScreenCoordinatorAction {
case editRoles(RoomRolesAndPermissionsScreenRole)
case editPermissions(permissions: RoomPermissions)
case editPermissions(ownPowerLevel: RoomPowerLevel, permissions: RoomPermissions)
case demotedOwnUser
}
@@ -44,8 +44,8 @@ final class RoomRolesAndPermissionsScreenCoordinator: CoordinatorProtocol {
switch action {
case .editRoles(let role):
actionsSubject.send(.editRoles(role))
case .editPermissions(let permissions):
actionsSubject.send(.editPermissions(permissions: permissions))
case .editPermissions(let ownPowerLevel, let permissions):
actionsSubject.send(.editPermissions(ownPowerLevel: ownPowerLevel, permissions: permissions))
case .demotedOwnUser:
actionsSubject.send(.demotedOwnUser)
}

View File

@@ -12,13 +12,13 @@ enum RoomRolesAndPermissionsScreenViewModelAction {
/// The user would like to edit member roles.
case editRoles(RoomRolesAndPermissionsScreenRole)
/// The user would like to edit room permissions.
case editPermissions(permissions: RoomPermissions)
case editPermissions(ownPowerLevel: RoomPowerLevel, permissions: RoomPermissions)
/// The user has demoted themself.
case demotedOwnUser
}
struct RoomRolesAndPermissionsScreenViewState: BindableState {
var ownRole: RoomRole
var ownPowerLevel: RoomPowerLevel
var administratorsAndOwnersCount: Int?
/// The number of administrators in the room.

View File

@@ -26,7 +26,7 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM
self.roomProxy = roomProxy
self.userIndicatorController = userIndicatorController
self.analytics = analytics
super.init(initialViewState: RoomRolesAndPermissionsScreenViewState(ownRole: roomProxy.membersPublisher.value.first { $0.userID == roomProxy.ownUserID }?.role ?? .administrator,
super.init(initialViewState: RoomRolesAndPermissionsScreenViewState(ownPowerLevel: roomProxy.membersPublisher.value.first { $0.userID == roomProxy.ownUserID }?.powerLevel ?? .value(Int(RoomRole.administrator.powerLevelValue)),
permissions: initialPermissions))
// Automatically update the admin/moderator counts.
@@ -91,7 +91,7 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM
state.administratorCount = members.filter { $0.role == .administrator && $0.isActive }.count
state.moderatorCount = members.filter { $0.role == .moderator && $0.isActive }.count
if let ownUser = members.first(where: { $0.userID == roomProxy.ownUserID }) {
state.ownRole = ownUser.role
state.ownPowerLevel = ownUser.powerLevel
}
}
@@ -132,7 +132,7 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM
MXLog.error("Missing permissions.")
return
}
actionsSubject.send(.editPermissions(permissions: permissions))
actionsSubject.send(.editPermissions(ownPowerLevel: state.ownPowerLevel, permissions: permissions))
}
private func resetPermissions() async {

View File

@@ -27,7 +27,7 @@ struct RoomRolesAndPermissionsScreen: View {
private var rolesSection: some View {
Section {
if context.viewState.ownRole == .creator {
if context.viewState.ownPowerLevel.role == .creator {
ListRow(label: .default(title: L10n.screenRoomRolesAndPermissionsAdminsAndOwners,
icon: \.admin),
details: administratorOrOwnersDetails,
@@ -53,7 +53,7 @@ struct RoomRolesAndPermissionsScreen: View {
})
.accessibilityIdentifier(A11yIdentifiers.roomRolesAndPermissionsScreen.moderators)
if context.viewState.ownRole != .creator {
if context.viewState.ownPowerLevel.role != .creator {
ListRow(label: .default(title: L10n.screenRoomRolesAndPermissionsChangeMyRole,
icon: \.edit),
kind: .button {

View File

@@ -10,24 +10,29 @@ import Foundation
import MatrixRustSDK
struct RoomPermissionsSetting: Identifiable {
var id: KeyPath<RoomPermissions, RoomRole> { keyPath }
static let allValues: [(title: String, tag: RoomRole)] = [(title: L10n.screenRoomChangePermissionsAdministrators, tag: .administrator),
(title: L10n.screenRoomChangePermissionsModerators, tag: .moderator),
(title: L10n.screenRoomChangePermissionsEveryone, tag: .user)]
var id: KeyPath<RoomPermissions, Int64> { keyPath }
/// The title of this setting.
let title: String
/// The selected role of this setting.
var value: RoomRole
/// All of the available roles that this setting can be configured with.
var allValues: [(title: String, tag: RoomRole)] {
[
(title: L10n.screenRoomChangePermissionsAdministrators, tag: .administrator),
(title: L10n.screenRoomChangePermissionsModerators, tag: .moderator),
(title: L10n.screenRoomChangePermissionsEveryone, tag: .user)
]
}
var value: Int64
let ownPowerLevel: RoomPowerLevel
var roleValue: RoomRole {
get {
RoomRole(powerLevelValue: value)
} set {
value = newValue.powerLevelValue
}
}
/// The `RoomPermissions` property that this setting is for.
let keyPath: KeyPath<RoomPermissions, RoomRole>
let keyPath: KeyPath<RoomPermissions, Int64>
/// The `RoomPowerLevelChanges` property that this setting is saved into.
var rustKeyPath: WritableKeyPath<RoomPowerLevelChanges, Int64?> {
switch keyPath {
@@ -45,46 +50,75 @@ struct RoomPermissionsSetting: Identifiable {
default: fatalError("Unexpected key path: \(keyPath)")
}
}
/// Can the setting be edited
var isDisabled: Bool {
switch ownPowerLevel {
case .value(let ownValue):
ownValue < value
case .infinite:
false
}
}
/// All of the available roles that this setting can be configured with.
var availableValues: [(title: String, tag: RoomRole)] {
if isDisabled {
Self.allValues.filter { $0.tag == RoomRole(powerLevelValue: value) }
} else {
Self.allValues.filter { $0.tag <= ownPowerLevel.role }
}
}
init(title: String,
value: Int64,
ownPowerLevel: RoomPowerLevel,
keyPath: KeyPath<RoomPermissions, Int64>) {
self.ownPowerLevel = ownPowerLevel
self.title = title
self.value = value
self.keyPath = keyPath
}
}
struct RoomPermissions {
/// The level required to ban a user.
var ban: RoomRole
var ban: Int64
/// The level required to invite a user.
var invite: RoomRole
var invite: Int64
/// The level required to kick a user.
var kick: RoomRole
var kick: Int64
/// The level required to redact an event.
var redact: RoomRole
var redact: Int64
/// The default level required to send message events.
var eventsDefault: RoomRole
var eventsDefault: Int64
/// The default level required to send state events.
var stateDefault: RoomRole
var stateDefault: Int64
/// The default power level for every user in the room.
var usersDefault: RoomRole
var usersDefault: Int64
/// The level required to change the room's name.
var roomName: RoomRole
var roomName: Int64
/// The level required to change the room's avatar.
var roomAvatar: RoomRole
var roomAvatar: Int64
/// The level required to change the room's topic.
var roomTopic: RoomRole
var roomTopic: Int64
/// The level required to add/remove childrens from a space.
var spaceChild: RoomRole
var spaceChild: Int64
}
extension RoomPermissions {
/// Create permissions from the room's power levels.
init(powerLevels: RoomPowerLevelsValues) {
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)
spaceChild = RoomRole(powerLevelValue: powerLevels.spaceChild)
ban = powerLevels.ban
invite = powerLevels.invite
kick = powerLevels.kick
redact = powerLevels.redact
eventsDefault = powerLevels.eventsDefault
stateDefault = powerLevels.stateDefault
usersDefault = powerLevels.usersDefault
roomName = powerLevels.roomName
roomAvatar = powerLevels.roomAvatar
roomTopic = powerLevels.roomTopic
spaceChild = powerLevels.spaceChild
}
}

View File

@@ -30,6 +30,10 @@ enum RoomPowerLevel: Hashable, Comparable {
case .value(let value): .value(value: Int64(value))
}
}
var role: RoomRole {
RoomRole(powerLevel: self)
}
}
extension PowerLevel {

View File

@@ -110,21 +110,25 @@ extension RoomRole {
/// 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 {
switch powerLevel {
case .infinite:
fatalError("Impossible")
case .value(let value):
return Int64(value)
}
}
var powerLevel: RoomPowerLevel {
guard self != .owner else {
// Would be better if the SDK would return this, maybe a `suggestedPowerLevelValueForRole` function would solve the problem
return 150
return .value(150)
}
do {
switch try suggestedPowerLevelForRole(role: rustRole) {
case .infinite:
fatalError("Impossible")
case .value(let value):
return value
}
return try RoomPowerLevel(rustPowerLevel: suggestedPowerLevelForRole(role: rustRole))
} catch {
MXLog.error("Falied to convert role to power level value: \(error)")
return 0
return .value(0)
}
}
}

View File

@@ -26,18 +26,44 @@ class RoomChangePermissionsScreenViewModelTests: XCTestCase {
XCTFail("There should be a setting for the room avatar.")
return
}
XCTAssertEqual(context.settings[.roomDetails]?[index].value, .moderator)
XCTAssertEqual(context.settings[.roomDetails]?[index].roleValue, .moderator)
XCTAssertFalse(context.viewState.hasChanges)
// When updating a setting.
let setting = RoomPermissionsSetting(title: "", value: .user, keyPath: \.roomAvatar)
let setting = RoomPermissionsSetting(title: "",
value: RoomRole.user.powerLevelValue,
ownPowerLevel: RoomRole.creator.powerLevel,
keyPath: \.roomAvatar)
XCTAssertFalse(setting.isDisabled)
XCTAssertEqual(setting.availableValues.map(\.tag), RoomPermissionsSetting.allValues.map(\.tag))
context.settings[.roomDetails]?[index] = setting
// Then the setting should update and the changes should be flagged.
XCTAssertEqual(context.settings[.roomDetails]?[index].value, .user)
XCTAssertEqual(context.settings[.roomDetails]?[index].roleValue, .user)
XCTAssertTrue(context.viewState.hasChanges)
}
func testSettingsCantBeChanged() {
setUp(isSpace: false, ownPowerLevel: .value(25))
// Given a screen with no changes.
guard let index = context.settings[.roomDetails]?.firstIndex(where: { $0.keyPath == \.roomAvatar }) else {
XCTFail("There should be a setting for the room avatar.")
return
}
XCTAssertEqual(context.settings[.roomDetails]?[index].roleValue, .moderator)
XCTAssertEqual(context.settings[.roomDetails]?[index].isDisabled, true)
XCTAssertEqual(context.settings[.roomDetails]?[index].availableValues.count, 1)
XCTAssertFalse(context.viewState.hasChanges)
guard let index = context.settings[.messagesAndContent]?.firstIndex(where: { $0.keyPath == \.eventsDefault }) else {
XCTFail("There should be a setting for the events.")
return
}
XCTAssertEqual(context.settings[.messagesAndContent]?[index].roleValue, .user)
XCTAssertEqual(context.settings[.messagesAndContent]?[index].isDisabled, false)
XCTAssertEqual(context.settings[.messagesAndContent]?[index].availableValues.count, 1)
}
func testSave() async throws {
setUp(isSpace: false)
// Given a screen with changes.
@@ -45,8 +71,13 @@ class RoomChangePermissionsScreenViewModelTests: XCTestCase {
XCTFail("There should be a setting for the room avatar.")
return
}
context.settings[.roomDetails]?[index] = RoomPermissionsSetting(title: "", value: .user, keyPath: \.roomAvatar)
XCTAssertEqual(context.settings[.roomDetails]?[index].value, .user)
context.settings[.roomDetails]?[index] = RoomPermissionsSetting(title: "",
value: RoomRole.user.powerLevelValue,
ownPowerLevel: RoomRole.creator.powerLevel,
keyPath: \.roomAvatar)
XCTAssertEqual(context.settings[.roomDetails]?[index].roleValue, .user)
XCTAssertEqual(context.settings[.roomDetails]?[index].isDisabled, false)
XCTAssertEqual(context.settings[.roomDetails]?[index].availableValues.map(\.tag), RoomPermissionsSetting.allValues.map(\.tag))
XCTAssertTrue(context.viewState.hasChanges)
XCTAssertEqual(context.settings.count, 3)
@@ -89,9 +120,10 @@ class RoomChangePermissionsScreenViewModelTests: XCTestCase {
XCTAssertNotNil(context.settings[.manageSpace])
}
private func setUp(isSpace: Bool) {
private func setUp(isSpace: Bool, ownPowerLevel: RoomPowerLevel = RoomRole.creator.powerLevel) {
roomProxy = JoinedRoomProxyMock(.init(isSpace: isSpace))
viewModel = RoomChangePermissionsScreenViewModel(currentPermissions: .init(powerLevels: .mock),
ownPowerLevel: ownPowerLevel,
roomProxy: roomProxy,
userIndicatorController: UserIndicatorControllerMock(),
analytics: ServiceLocator.shared.analytics)

View File

@@ -30,16 +30,16 @@ class RoomPermissionsTests: XCTestCase {
let permissions = RoomPermissions(powerLevels: powerLevels)
// Then the permissions should be created with values mapped to the correct role.
XCTAssertEqual(permissions.ban, .administrator)
XCTAssertEqual(permissions.invite, .administrator)
XCTAssertEqual(permissions.kick, .administrator)
XCTAssertEqual(permissions.redact, .moderator)
XCTAssertEqual(permissions.eventsDefault, .moderator)
XCTAssertEqual(permissions.stateDefault, .moderator)
XCTAssertEqual(permissions.usersDefault, .user)
XCTAssertEqual(permissions.roomName, .user)
XCTAssertEqual(permissions.roomAvatar, .user)
XCTAssertEqual(permissions.roomTopic, .user)
XCTAssertEqual(permissions.spaceChild, .administrator)
XCTAssertEqual(permissions.ban, RoomRole.administrator.powerLevelValue)
XCTAssertEqual(permissions.invite, RoomRole.administrator.powerLevelValue)
XCTAssertEqual(permissions.kick, RoomRole.administrator.powerLevelValue)
XCTAssertEqual(permissions.redact, RoomRole.moderator.powerLevelValue)
XCTAssertEqual(permissions.eventsDefault, RoomRole.moderator.powerLevelValue)
XCTAssertEqual(permissions.stateDefault, RoomRole.moderator.powerLevelValue)
XCTAssertEqual(permissions.usersDefault, RoomRole.user.powerLevelValue)
XCTAssertEqual(permissions.roomName, RoomRole.user.powerLevelValue)
XCTAssertEqual(permissions.roomAvatar, RoomRole.user.powerLevelValue)
XCTAssertEqual(permissions.roomTopic, RoomRole.user.powerLevelValue)
XCTAssertEqual(permissions.spaceChild, RoomRole.administrator.powerLevelValue)
}
}