mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
SDK Update + PowerLevels API update (#4366)
* update the sdk, and updated the power levels APIs Revert "update the sdk, and updated the power levels APIs" This reverts commit d3b291003d2b6fd6346ef7e445af4970fda62348. x * pr suggestions
This commit is contained in:
@@ -32,7 +32,7 @@ extension RoomInfoProxyMock {
|
||||
|
||||
id = configuration.id
|
||||
isEncrypted = false
|
||||
creator = nil
|
||||
creators = []
|
||||
displayName = configuration.name
|
||||
rawName = nil
|
||||
topic = nil
|
||||
|
||||
@@ -13272,7 +13272,7 @@ class RoomInfoProxyMock: RoomInfoProxyProtocol, @unchecked Sendable {
|
||||
set(value) { underlyingId = value }
|
||||
}
|
||||
var underlyingId: String!
|
||||
var creator: String?
|
||||
var creators: [String] = []
|
||||
var displayName: String?
|
||||
var rawName: String?
|
||||
var topic: String?
|
||||
@@ -13393,11 +13393,11 @@ class RoomMemberProxyMock: RoomMemberProxyProtocol, @unchecked Sendable {
|
||||
set(value) { underlyingIsIgnored = value }
|
||||
}
|
||||
var underlyingIsIgnored: Bool!
|
||||
var powerLevel: Int {
|
||||
var powerLevel: RoomPowerLevel {
|
||||
get { return underlyingPowerLevel }
|
||||
set(value) { underlyingPowerLevel = value }
|
||||
}
|
||||
var underlyingPowerLevel: Int!
|
||||
var underlyingPowerLevel: RoomPowerLevel!
|
||||
var role: RoomMemberRole {
|
||||
get { return underlyingRole }
|
||||
set(value) { underlyingRole = value }
|
||||
|
||||
@@ -36,7 +36,7 @@ extension RoomInfoProxyMock {
|
||||
|
||||
id = configuration.id
|
||||
isEncrypted = false
|
||||
creator = nil
|
||||
creators = []
|
||||
displayName = configuration.name
|
||||
rawName = nil
|
||||
topic = nil
|
||||
@@ -79,8 +79,8 @@ private extension RoomMember {
|
||||
avatarUrl: proxy.avatarURL?.absoluteString,
|
||||
membership: proxy.membership,
|
||||
isNameAmbiguous: proxy.disambiguatedDisplayName != proxy.displayName,
|
||||
powerLevel: Int64(proxy.powerLevel),
|
||||
normalizedPowerLevel: Int64(proxy.powerLevel),
|
||||
powerLevel: proxy.powerLevel.rustPowerLevel,
|
||||
normalizedPowerLevel: proxy.powerLevel.rustPowerLevel,
|
||||
isIgnored: proxy.isIgnored,
|
||||
suggestedRoleForPowerLevel: proxy.role,
|
||||
membershipChangeReason: proxy.membershipChangeReason)
|
||||
|
||||
@@ -165,7 +165,7 @@ extension RoomInfoProxyMock {
|
||||
|
||||
id = configuration.id
|
||||
isEncrypted = configuration.isEncrypted
|
||||
creator = nil
|
||||
creators = []
|
||||
displayName = configuration.name
|
||||
rawName = configuration.name
|
||||
topic = configuration.topic
|
||||
|
||||
@@ -32,7 +32,7 @@ extension RoomInfoProxyMock {
|
||||
|
||||
id = configuration.id
|
||||
isEncrypted = false
|
||||
creator = nil
|
||||
creators = []
|
||||
displayName = configuration.name
|
||||
rawName = nil
|
||||
topic = nil
|
||||
|
||||
@@ -16,7 +16,7 @@ struct RoomMemberProxyMockConfiguration {
|
||||
var membership: MembershipState
|
||||
var isIgnored = false
|
||||
|
||||
var powerLevel = 0
|
||||
var powerLevel = RoomPowerLevel(value: 0)
|
||||
var role = RoomMemberRole.user
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ extension RoomMemberProxyMock {
|
||||
displayName: "Me",
|
||||
avatarURL: .mockMXCUserAvatar,
|
||||
membership: .join,
|
||||
powerLevel: 100,
|
||||
powerLevel: .init(value: 100),
|
||||
role: .administrator))
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ extension RoomMemberProxyMock {
|
||||
RoomMemberProxyMock(with: .init(userID: "@admin:matrix.org",
|
||||
displayName: "Arthur",
|
||||
membership: .join,
|
||||
powerLevel: 100,
|
||||
powerLevel: .init(value: 100),
|
||||
role: .administrator))
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ extension RoomMemberProxyMock {
|
||||
RoomMemberProxyMock(with: .init(userID: "@mod:matrix.org",
|
||||
displayName: "Merlin",
|
||||
membership: .join,
|
||||
powerLevel: 50,
|
||||
powerLevel: .init(value: 50),
|
||||
role: .moderator))
|
||||
}
|
||||
|
||||
|
||||
@@ -86,5 +86,5 @@ enum ManageRoomMemberDetails {
|
||||
struct ManageRoomMemberPermissions {
|
||||
let canKick: Bool
|
||||
let canBan: Bool
|
||||
let ownPowerLevel: Int
|
||||
let ownPowerLevel: RoomPowerLevel
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ struct ManageRoomMemberSheetView: View {
|
||||
struct ManageRoomMemberSheetView_Previews: PreviewProvider, TestablePreview {
|
||||
static let allActionsViewModel = ManageRoomMemberSheetViewModel.mock()
|
||||
|
||||
static let allActionsDisabledViewModel = ManageRoomMemberSheetViewModel.mock(powerLevel: 0)
|
||||
static let allActionsDisabledViewModel = ManageRoomMemberSheetViewModel.mock(powerLevel: .init(value: 0))
|
||||
|
||||
static let kickOnlyViewModel = ManageRoomMemberSheetViewModel.mock(canBan: false)
|
||||
|
||||
@@ -100,7 +100,7 @@ private extension ManageRoomMemberSheetViewModel {
|
||||
static func mock(canKick: Bool = true,
|
||||
canBan: Bool = true,
|
||||
memberIsBanned: Bool = false,
|
||||
powerLevel: Int = 100) -> ManageRoomMemberSheetViewModel {
|
||||
powerLevel: RoomPowerLevel = .init(value: 100)) -> ManageRoomMemberSheetViewModel {
|
||||
let member = if memberIsBanned {
|
||||
RoomMemberDetails(withProxy: RoomMemberProxyMock.mockBanned[0])
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ class RoomChangePermissionsScreenViewModel: RoomChangePermissionsScreenViewModel
|
||||
var changes = RoomPowerLevelChanges()
|
||||
let changedSettings = state.bindings.settings.filter { state.currentPermissions[keyPath: $0.keyPath] != $0.value }
|
||||
for setting in changedSettings {
|
||||
changes[keyPath: setting.rustKeyPath] = setting.value.rustPowerLevel
|
||||
changes[keyPath: setting.rustKeyPath] = setting.value.powerLevelValue
|
||||
}
|
||||
|
||||
switch await roomProxy.applyPowerLevelChanges(changes) {
|
||||
|
||||
@@ -86,7 +86,8 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh
|
||||
let memberDetails = RoomMemberDetails(withProxy: member)
|
||||
|
||||
switch member.role {
|
||||
case .administrator:
|
||||
// TODO: Create a owner list
|
||||
case .administrator, .creator:
|
||||
administrators.append(memberDetails)
|
||||
case .moderator:
|
||||
moderators.append(memberDetails)
|
||||
@@ -139,7 +140,7 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh
|
||||
hideSavingIndicator()
|
||||
}
|
||||
|
||||
let promotingUpdates = state.membersToPromote.map { ($0.id, state.mode.rustPowerLevel) }
|
||||
let promotingUpdates = state.membersToPromote.map { ($0.id, state.mode.powerLevelValue) }
|
||||
let demotingUpdates = state.membersToDemote.map { ($0.id, Int64(0)) }
|
||||
|
||||
// A task we can await until the room's info gets modified with the new power levels.
|
||||
|
||||
@@ -154,7 +154,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
let manageMemeberViewModel = ManageRoomMemberSheetViewModel(memberDetails: .memberDetails(roomMember: member),
|
||||
permissions: .init(canKick: state.canKickUsers,
|
||||
canBan: state.canBanUsers,
|
||||
ownPowerLevel: currentUserProxy?.powerLevel ?? 0),
|
||||
ownPowerLevel: currentUserProxy?.powerLevel ?? .init(value: 0)),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: userIndicatorController,
|
||||
analyticsService: analytics,
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM
|
||||
// Note: Ignore the first value as the publisher is backed by a current value subject.
|
||||
let infoTask = Task { await roomProxy.infoPublisher.dropFirst().values.first { _ in true } }
|
||||
|
||||
switch await roomProxy.updatePowerLevelsForUsers([(userID: roomProxy.ownUserID, powerLevel: role.rustPowerLevel)]) {
|
||||
switch await roomProxy.updatePowerLevelsForUsers([(userID: roomProxy.ownUserID, powerLevel: role.powerLevelValue)]) {
|
||||
case .success:
|
||||
_ = await infoTask.value
|
||||
await roomProxy.updateMembers()
|
||||
|
||||
@@ -285,7 +285,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
let viewModel = ManageRoomMemberSheetViewModel(memberDetails: memberDetails,
|
||||
permissions: .init(canKick: state.canCurrentUserKick,
|
||||
canBan: state.canCurrentUserBan,
|
||||
ownPowerLevel: currentUserProxy?.powerLevel ?? 0),
|
||||
ownPowerLevel: currentUserProxy?.powerLevel ?? .init(value: 0)),
|
||||
roomProxy: roomProxy,
|
||||
userIndicatorController: userIndicatorController,
|
||||
analyticsService: analyticsService,
|
||||
|
||||
@@ -12,7 +12,7 @@ struct RoomInfoProxy: RoomInfoProxyProtocol {
|
||||
let roomInfo: RoomInfo
|
||||
|
||||
var id: String { roomInfo.id }
|
||||
var creator: String? { roomInfo.creator }
|
||||
var creators: [String] { roomInfo.creators ?? [] }
|
||||
var displayName: String? { roomInfo.displayName }
|
||||
var rawName: String? { roomInfo.rawName }
|
||||
var topic: String? { roomInfo.topic }
|
||||
|
||||
@@ -26,7 +26,7 @@ protocol BaseRoomInfoProxyProtocol {
|
||||
// sourcery: AutoMockable
|
||||
protocol RoomInfoProxyProtocol: BaseRoomInfoProxyProtocol {
|
||||
var id: String { get }
|
||||
var creator: String? { get }
|
||||
var creators: [String] { get }
|
||||
var displayName: String? { get }
|
||||
var rawName: String? { get }
|
||||
var topic: String? { get }
|
||||
|
||||
@@ -21,7 +21,7 @@ struct RoomMemberDetails: Identifiable, Hashable {
|
||||
|
||||
enum Role { case administrator, moderator, user }
|
||||
let role: Role
|
||||
let powerLevel: Int
|
||||
let powerLevel: RoomPowerLevel
|
||||
|
||||
func matches(searchQuery: String) -> Bool {
|
||||
guard !searchQuery.isEmpty else { return true }
|
||||
@@ -47,7 +47,8 @@ extension RoomMemberDetails {
|
||||
extension RoomMemberDetails.Role {
|
||||
init(_ role: RoomMemberRole) {
|
||||
self = switch role {
|
||||
case .administrator: .administrator
|
||||
// TODO: Implement creator role
|
||||
case .creator, .administrator: .administrator
|
||||
case .moderator: .moderator
|
||||
case .user: .user
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ final class RoomMemberProxy: RoomMemberProxyProtocol {
|
||||
|
||||
var isIgnored: Bool { member.isIgnored }
|
||||
|
||||
var powerLevel: Int { Int(member.powerLevel) }
|
||||
var powerLevel: RoomPowerLevel { .init(rustPowerLevel: member.powerLevel) }
|
||||
|
||||
var role: RoomMemberRole { member.suggestedRoleForPowerLevel }
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ protocol RoomMemberProxyProtocol: AnyObject {
|
||||
|
||||
var isIgnored: Bool { get }
|
||||
|
||||
var powerLevel: Int { get }
|
||||
var powerLevel: RoomPowerLevel { get }
|
||||
|
||||
var role: RoomMemberRole { get }
|
||||
}
|
||||
|
||||
@@ -71,22 +71,27 @@ struct RoomPermissions {
|
||||
extension RoomPermissions {
|
||||
/// Create permissions from the room's power levels.
|
||||
init(powerLevels: RoomPowerLevelsValues) {
|
||||
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)
|
||||
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(rustPowerLevel: Int64) {
|
||||
self.init(suggestedRoleForPowerLevel(powerLevel: rustPowerLevel))
|
||||
init(powerLevelValue: Int64) {
|
||||
do {
|
||||
try self.init(suggestedRoleForPowerLevel(powerLevel: .value(value: powerLevelValue)))
|
||||
} catch {
|
||||
MXLog.error("Falied to convert power level value to role: \(error)")
|
||||
self.init(.user)
|
||||
}
|
||||
}
|
||||
|
||||
var rustRole: RoomMemberRole {
|
||||
@@ -100,7 +105,20 @@ extension RoomMemberDetails.Role {
|
||||
}
|
||||
}
|
||||
|
||||
var rustPowerLevel: Int64 {
|
||||
suggestedPowerLevelForRole(role: rustRole)
|
||||
/// 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 {
|
||||
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
|
||||
case .value(let value):
|
||||
return value
|
||||
}
|
||||
} catch {
|
||||
MXLog.error("Falied to convert role to power level value: \(error)")
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// 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 RoomPowerLevel: Hashable, Comparable {
|
||||
case value(Int)
|
||||
case infinite
|
||||
|
||||
init(rustPowerLevel: PowerLevel) {
|
||||
self = rustPowerLevel.toRoomPowerLevel
|
||||
}
|
||||
|
||||
init(value: Int) {
|
||||
self = .value(value)
|
||||
}
|
||||
|
||||
init(value: Int64) {
|
||||
self = .value(Int(value))
|
||||
}
|
||||
|
||||
var rustPowerLevel: PowerLevel {
|
||||
switch self {
|
||||
case .infinite: .infinite
|
||||
case .value(let value): .value(value: Int64(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension PowerLevel {
|
||||
var toRoomPowerLevel: RoomPowerLevel {
|
||||
switch self {
|
||||
case .infinite: .infinite
|
||||
case .value(let value): .value(Int(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,13 @@ struct RoomPowerLevelsProxy: RoomPowerLevelsProxyProtocol {
|
||||
}
|
||||
|
||||
func suggestedRole(forUser userID: String) -> RoomMemberRole {
|
||||
let powerLevel = powerLevels.userPowerLevels()[userID] ?? values.usersDefault
|
||||
return suggestedRoleForPowerLevel(powerLevel: powerLevel)
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user