Skip to content

Commit

Permalink
Update the SDK adopting new power levels APIs.
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Mar 8, 2024
1 parent b54d87e commit cea8e0a
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 183 deletions.
2 changes: 1 addition & 1 deletion ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7112,7 +7112,7 @@
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
requirement = {
kind = exactVersion;
version = 1.1.46;
version = 1.1.47;
};
};
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
"state" : {
"revision" : "f0b060274251263c6470d90d5877af2856c0da14",
"version" : "1.1.46"
"revision" : "57931f2aca93dab50cb86352081a6cdd6cdcf61b",
"version" : "1.1.47"
}
},
{
Expand Down
22 changes: 11 additions & 11 deletions ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2712,21 +2712,21 @@ class RoomProxyMock: RoomProxyProtocol {
return flagAsFavouriteReturnValue
}
}
//MARK: - currentPowerLevelChanges
//MARK: - powerLevels

var currentPowerLevelChangesCallsCount = 0
var currentPowerLevelChangesCalled: Bool {
return currentPowerLevelChangesCallsCount > 0
var powerLevelsCallsCount = 0
var powerLevelsCalled: Bool {
return powerLevelsCallsCount > 0
}
var currentPowerLevelChangesReturnValue: Result<RoomPowerLevelChanges, RoomProxyError>!
var currentPowerLevelChangesClosure: (() async -> Result<RoomPowerLevelChanges, RoomProxyError>)?
var powerLevelsReturnValue: Result<RoomPowerLevels, RoomProxyError>!
var powerLevelsClosure: (() async -> Result<RoomPowerLevels, RoomProxyError>)?

func currentPowerLevelChanges() async -> Result<RoomPowerLevelChanges, RoomProxyError> {
currentPowerLevelChangesCallsCount += 1
if let currentPowerLevelChangesClosure = currentPowerLevelChangesClosure {
return await currentPowerLevelChangesClosure()
func powerLevels() async -> Result<RoomPowerLevels, RoomProxyError> {
powerLevelsCallsCount += 1
if let powerLevelsClosure = powerLevelsClosure {
return await powerLevelsClosure()
} else {
return currentPowerLevelChangesReturnValue
return powerLevelsReturnValue
}
}
//MARK: - applyPowerLevelChanges
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Mocks/RoomProxyMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ extension RoomProxyMock {
underlyingIsFavourite = false
flagAsFavouriteReturnValue = .success(())

currentPowerLevelChangesReturnValue = .success(.init())
powerLevelsReturnValue = .success(.mock)
applyPowerLevelChangesReturnValue = .success(())
updatePowerLevelsForUsersReturnValue = .success(())
canUserUserIDSendStateEventClosure = { [weak self] userID, _ in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct RoomChangePermissionsScreenViewState: BindableState {

/// Whether or not there are and changes to be saved.
var hasChanges: Bool {
bindings.settings.contains { currentPermissions[keyPath: $0.keyPath] ?? RoomPermissions.defaultValue(for: $0.keyPath) != $0.value }
bindings.settings.contains { currentPermissions[keyPath: $0.keyPath] != $0.value }
}
}

Expand Down Expand Up @@ -61,42 +61,42 @@ extension RoomChangePermissionsScreenViewState {
switch group {
case .roomDetails:
let settings = [
RoomPermissionsSetting(keyPath: \.roomName,
value: currentPermissions.roomName ?? RoomPermissions.defaultValue(for: \.roomName),
title: L10n.screenRoomChangePermissionsRoomName),
RoomPermissionsSetting(keyPath: \.roomAvatar,
value: currentPermissions.roomAvatar ?? RoomPermissions.defaultValue(for: \.roomAvatar),
title: L10n.screenRoomChangePermissionsRoomAvatar),
RoomPermissionsSetting(keyPath: \.roomTopic,
value: currentPermissions.roomTopic ?? RoomPermissions.defaultValue(for: \.roomTopic),
title: L10n.screenRoomChangePermissionsRoomTopic)
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRoomName,
value: currentPermissions.roomName,
keyPath: \.roomName),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRoomAvatar,
value: currentPermissions.roomAvatar,
keyPath: \.roomAvatar),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRoomTopic,
value: currentPermissions.roomTopic,
keyPath: \.roomTopic)
]

self.init(title: L10n.screenRoomChangePermissionsRoomDetails, currentPermissions: currentPermissions, bindings: .init(settings: settings))

case .messagesAndContent:
let settings = [
RoomPermissionsSetting(keyPath: \.eventsDefault,
value: currentPermissions.eventsDefault ?? RoomPermissions.defaultValue(for: \.eventsDefault),
title: L10n.screenRoomChangePermissionsSendMessages),
RoomPermissionsSetting(keyPath: \.redact,
value: currentPermissions.redact ?? RoomPermissions.defaultValue(for: \.redact),
title: L10n.screenRoomChangePermissionsDeleteMessages)
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsSendMessages,
value: currentPermissions.eventsDefault,
keyPath: \.eventsDefault),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsDeleteMessages,
value: currentPermissions.redact,
keyPath: \.redact)
]

self.init(title: L10n.screenRoomChangePermissionsMessagesAndContent, currentPermissions: currentPermissions, bindings: .init(settings: settings))

case .memberModeration:
let settings = [
RoomPermissionsSetting(keyPath: \.invite,
value: currentPermissions.invite ?? RoomPermissions.defaultValue(for: \.invite),
title: L10n.screenRoomChangePermissionsInvitePeople),
RoomPermissionsSetting(keyPath: \.kick,
value: currentPermissions.kick ?? RoomPermissions.defaultValue(for: \.kick),
title: L10n.screenRoomChangePermissionsRemovePeople),
RoomPermissionsSetting(keyPath: \.ban,
value: currentPermissions.ban ?? RoomPermissions.defaultValue(for: \.ban),
title: L10n.screenRoomChangePermissionsBanPeople)
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsInvitePeople,
value: currentPermissions.invite,
keyPath: \.invite),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsRemovePeople,
value: currentPermissions.kick,
keyPath: \.kick),
RoomPermissionsSetting(title: L10n.screenRoomChangePermissionsBanPeople,
value: currentPermissions.ban,
keyPath: \.ban)
]

self.init(title: L10n.screenRoomChangePermissionsMemberModeration, currentPermissions: currentPermissions, bindings: .init(settings: settings))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//

import Combine
import MatrixRustSDK
import SwiftUI

typealias RoomChangePermissionsScreenViewModelType = StateStoreViewModel<RoomChangePermissionsScreenViewState, RoomChangePermissionsScreenViewAction>
Expand Down Expand Up @@ -62,22 +63,22 @@ class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModel
hideLoadingIndicator()
}

var updatedPermissions = RoomPermissions()
var changes = RoomPowerLevelChanges()
for setting in state.bindings.settings {
updatedPermissions[keyPath: setting.keyPath] = setting.value
changes[keyPath: setting.rustKeyPath] = setting.value.rustPowerLevel
}

switch await roomProxy.applyPowerLevelChanges(updatedPermissions.makePowerLevelChanges()) {
switch await roomProxy.applyPowerLevelChanges(changes) {
case .success:
MXLog.info("Success")
case .failure:
context.alertInfo = AlertInfo(id: .generic)
return
}

switch await roomProxy.currentPowerLevelChanges() {
case .success(let powerLevelChanges):
state.currentPermissions = .init(powerLevelChanges: powerLevelChanges)
switch await roomProxy.powerLevels() {
case .success(let powerLevels):
state.currentPermissions = .init(powerLevels: powerLevels)
case .failure:
context.alertInfo = AlertInfo(id: .generic)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct RoomChangePermissionsScreen_Previews: PreviewProvider, TestablePreview {
}

static func makeViewModel(group: RoomRolesAndPermissionsScreenPermissionsGroup) -> RoomChangePermissionsScreenViewModel {
RoomChangePermissionsScreenViewModel(currentPermissions: .default,
RoomChangePermissionsScreenViewModel(currentPermissions: .init(powerLevels: .mock),
group: group,
roomProxy: RoomProxyMock(with: .init()),
userIndicatorController: UserIndicatorControllerMock())
Expand Down
129 changes: 61 additions & 68 deletions ElementX/Sources/Services/Room/RoomPermissions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,100 +18,78 @@ import Foundation
import MatrixRustSDK

struct RoomPermissionsSetting: Identifiable {
var id: KeyPath<RoomPermissions, RoomMemberDetails.Role?> { keyPath }
var id: KeyPath<RoomPermissions, RoomMemberDetails.Role> { keyPath }

let keyPath: WritableKeyPath<RoomPermissions, RoomMemberDetails.Role?>
var value: RoomMemberDetails.Role
/// The title of this setting.
let title: String

/// The selected role of this setting.
var value: RoomMemberDetails.Role
/// All of the available roles that this setting can be configured with.
var allValues: [(title: String, tag: RoomMemberDetails.Role)] {
[
(title: L10n.screenRoomChangePermissionsAdministrators, tag: .administrator),
(title: L10n.screenRoomChangePermissionsModerators, tag: .moderator),
(title: L10n.screenRoomChangePermissionsEveryone, tag: .user)
]
}

/// The `RoomPermissions` property that this setting is for.
let keyPath: KeyPath<RoomPermissions, RoomMemberDetails.Role>
/// The `RoomPowerLevelChanges` property that this setting is saved into.
var rustKeyPath: WritableKeyPath<RoomPowerLevelChanges, Int64?> {
switch keyPath {
case \.ban: \.ban
case \.invite: \.invite
case \.kick: \.kick
case \.redact: \.redact
case \.eventsDefault: \.eventsDefault
case \.stateDefault: \.stateDefault
case \.usersDefault: \.usersDefault
case \.roomName: \.roomName
case \.roomAvatar: \.roomAvatar
case \.roomTopic: \.roomTopic
default: fatalError("Unexpected key path: \(keyPath)")
}
}
}

struct RoomPermissions {
/// The level required to ban a user.
var ban: RoomMemberDetails.Role?
var ban: RoomMemberDetails.Role
/// The level required to invite a user.
var invite: RoomMemberDetails.Role?
var invite: RoomMemberDetails.Role
/// The level required to kick a user.
var kick: RoomMemberDetails.Role?
var kick: RoomMemberDetails.Role
/// The level required to redact an event.
var redact: RoomMemberDetails.Role?
var redact: RoomMemberDetails.Role
/// The default level required to send message events.
var eventsDefault: RoomMemberDetails.Role?
var eventsDefault: RoomMemberDetails.Role
/// The default level required to send state events.
var stateDefault: RoomMemberDetails.Role?
var stateDefault: RoomMemberDetails.Role
/// The default power level for every user in the room.
var usersDefault: RoomMemberDetails.Role?
var usersDefault: RoomMemberDetails.Role
/// The level required to change the room's name.
var roomName: RoomMemberDetails.Role?
var roomName: RoomMemberDetails.Role
/// The level required to change the room's avatar.
var roomAvatar: RoomMemberDetails.Role?
var roomAvatar: RoomMemberDetails.Role
/// The level required to change the room's topic.
var roomTopic: RoomMemberDetails.Role?
var roomTopic: RoomMemberDetails.Role
}

extension RoomPermissions {
/// Returns the default value for a particular permission.
static func defaultValue(for keyPath: KeyPath<RoomPermissions, RoomMemberDetails.Role?>) -> RoomMemberDetails.Role {
switch keyPath {
case \.ban: .moderator
case \.invite: .user
case \.kick: .moderator
case \.redact: .moderator
case \.eventsDefault: .user
case \.stateDefault: .moderator
case \.usersDefault: .user
case \.roomName: .moderator
case \.roomAvatar: .moderator
case \.roomTopic: .moderator
default: fatalError("Unexpected key path: \(keyPath)")
}
}

/// Constructs a set of permissions using the default values.
static var `default`: RoomPermissions {
RoomPermissions(ban: defaultValue(for: \.ban),
invite: defaultValue(for: \.invite),
kick: defaultValue(for: \.kick),
redact: defaultValue(for: \.redact),
eventsDefault: defaultValue(for: \.eventsDefault),
stateDefault: defaultValue(for: \.stateDefault),
usersDefault: defaultValue(for: \.usersDefault),
roomName: defaultValue(for: \.roomName),
roomAvatar: defaultValue(for: \.roomAvatar),
roomTopic: defaultValue(for: \.roomTopic))
}

init(powerLevelChanges: RoomPowerLevelChanges) {
ban = powerLevelChanges.ban.map(RoomMemberDetails.Role.init)
invite = powerLevelChanges.invite.map(RoomMemberDetails.Role.init)
kick = powerLevelChanges.kick.map(RoomMemberDetails.Role.init)
redact = powerLevelChanges.redact.map(RoomMemberDetails.Role.init)
eventsDefault = powerLevelChanges.eventsDefault.map(RoomMemberDetails.Role.init)
stateDefault = powerLevelChanges.stateDefault.map(RoomMemberDetails.Role.init)
usersDefault = powerLevelChanges.usersDefault.map(RoomMemberDetails.Role.init)
roomName = powerLevelChanges.roomName.map(RoomMemberDetails.Role.init)
roomAvatar = powerLevelChanges.roomAvatar.map(RoomMemberDetails.Role.init)
roomTopic = powerLevelChanges.roomTopic.map(RoomMemberDetails.Role.init)
}

func makePowerLevelChanges() -> RoomPowerLevelChanges {
RoomPowerLevelChanges(ban: ban?.rustPowerLevel,
invite: invite?.rustPowerLevel,
kick: kick?.rustPowerLevel,
redact: redact?.rustPowerLevel,
eventsDefault: eventsDefault?.rustPowerLevel,
stateDefault: stateDefault?.rustPowerLevel,
usersDefault: usersDefault?.rustPowerLevel,
roomName: roomName?.rustPowerLevel,
roomAvatar: roomAvatar?.rustPowerLevel,
roomTopic: roomTopic?.rustPowerLevel)
/// Create permissions from the room's power levels.
init(powerLevels: RoomPowerLevels) {
ban = RoomMemberDetails.Role(rustPowerLevel: powerLevels.ban)
invite = RoomMemberDetails.Role(rustPowerLevel: powerLevels.invite)
kick = RoomMemberDetails.Role(rustPowerLevel: powerLevels.kick)
redact = RoomMemberDetails.Role(rustPowerLevel: powerLevels.redact)
eventsDefault = RoomMemberDetails.Role(rustPowerLevel: powerLevels.eventsDefault)
stateDefault = RoomMemberDetails.Role(rustPowerLevel: powerLevels.stateDefault)
usersDefault = RoomMemberDetails.Role(rustPowerLevel: powerLevels.usersDefault)
roomName = RoomMemberDetails.Role(rustPowerLevel: powerLevels.roomName)
roomAvatar = RoomMemberDetails.Role(rustPowerLevel: powerLevels.roomAvatar)
roomTopic = RoomMemberDetails.Role(rustPowerLevel: powerLevels.roomTopic)
}
}

Expand All @@ -135,3 +113,18 @@ extension RoomMemberDetails.Role {
suggestedPowerLevelForRole(role: rustRole)
}
}

extension RoomPowerLevels {
static var mock: RoomPowerLevels {
RoomPowerLevels(ban: 50,
invite: 0,
kick: 50,
redact: 50,
eventsDefault: 0,
stateDefault: 50,
usersDefault: 0,
roomName: 50,
roomAvatar: 50,
roomTopic: 50)
}
}
4 changes: 2 additions & 2 deletions ElementX/Sources/Services/Room/RoomProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -373,9 +373,9 @@ class RoomProxy: RoomProxyProtocol {

// MARK: - Power Levels

func currentPowerLevelChanges() async -> Result<RoomPowerLevelChanges, RoomProxyError> {
func powerLevels() async -> Result<RoomPowerLevels, RoomProxyError> {
do {
return try await .success(room.buildPowerLevelChangesFromCurrent())
return try await .success(room.getPowerLevels())
} catch {
MXLog.error("Failed building the current power level settings: \(error)")
return .failure(.failedCheckingPermission)
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Services/Room/RoomProxyProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protocol RoomProxyProtocol {

// MARK: - Power Levels

func currentPowerLevelChanges() async -> Result<RoomPowerLevelChanges, RoomProxyError>
func powerLevels() async -> Result<RoomPowerLevels, RoomProxyError>
func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result<Void, RoomProxyError>
func updatePowerLevelsForUsers(_ updates: [(userID: String, powerLevel: Int64)]) async -> Result<Void, RoomProxyError>
func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result<Bool, RoomProxyError>
Expand Down
Loading

0 comments on commit cea8e0a

Please sign in to comment.