mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
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:
@@ -13435,76 +13435,6 @@ class RoomPowerLevelsProxyMock: RoomPowerLevelsProxyProtocol, @unchecked Sendabl
|
|||||||
var underlyingValues: RoomPowerLevelsValues!
|
var underlyingValues: RoomPowerLevelsValues!
|
||||||
var userPowerLevels: [String: Int64] = [:]
|
var userPowerLevels: [String: Int64] = [:]
|
||||||
|
|
||||||
//MARK: - suggestedRole
|
|
||||||
|
|
||||||
var suggestedRoleForUserUnderlyingCallsCount = 0
|
|
||||||
var suggestedRoleForUserCallsCount: Int {
|
|
||||||
get {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
return suggestedRoleForUserUnderlyingCallsCount
|
|
||||||
} else {
|
|
||||||
var returnValue: Int? = nil
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
returnValue = suggestedRoleForUserUnderlyingCallsCount
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
suggestedRoleForUserUnderlyingCallsCount = newValue
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
suggestedRoleForUserUnderlyingCallsCount = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var suggestedRoleForUserCalled: Bool {
|
|
||||||
return suggestedRoleForUserCallsCount > 0
|
|
||||||
}
|
|
||||||
var suggestedRoleForUserReceivedUserID: String?
|
|
||||||
var suggestedRoleForUserReceivedInvocations: [String] = []
|
|
||||||
|
|
||||||
var suggestedRoleForUserUnderlyingReturnValue: RoomMemberRole!
|
|
||||||
var suggestedRoleForUserReturnValue: RoomMemberRole! {
|
|
||||||
get {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
return suggestedRoleForUserUnderlyingReturnValue
|
|
||||||
} else {
|
|
||||||
var returnValue: RoomMemberRole? = nil
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
returnValue = suggestedRoleForUserUnderlyingReturnValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
if Thread.isMainThread {
|
|
||||||
suggestedRoleForUserUnderlyingReturnValue = newValue
|
|
||||||
} else {
|
|
||||||
DispatchQueue.main.sync {
|
|
||||||
suggestedRoleForUserUnderlyingReturnValue = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var suggestedRoleForUserClosure: ((String) -> RoomMemberRole)?
|
|
||||||
|
|
||||||
func suggestedRole(forUser userID: String) -> RoomMemberRole {
|
|
||||||
suggestedRoleForUserCallsCount += 1
|
|
||||||
suggestedRoleForUserReceivedUserID = userID
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.suggestedRoleForUserReceivedInvocations.append(userID)
|
|
||||||
}
|
|
||||||
if let suggestedRoleForUserClosure = suggestedRoleForUserClosure {
|
|
||||||
return suggestedRoleForUserClosure(userID)
|
|
||||||
} else {
|
|
||||||
return suggestedRoleForUserReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//MARK: - canOwnUser
|
//MARK: - canOwnUser
|
||||||
|
|
||||||
var canOwnUserSendMessageUnderlyingCallsCount = 0
|
var canOwnUserSendMessageUnderlyingCallsCount = 0
|
||||||
@@ -14157,6 +14087,70 @@ class RoomPowerLevelsProxyMock: RoomPowerLevelsProxyProtocol, @unchecked Sendabl
|
|||||||
return canOwnUserJoinCallReturnValue
|
return canOwnUserJoinCallReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//MARK: - canOwnUserEditRolesAndPermissions
|
||||||
|
|
||||||
|
var canOwnUserEditRolesAndPermissionsUnderlyingCallsCount = 0
|
||||||
|
var canOwnUserEditRolesAndPermissionsCallsCount: Int {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return canOwnUserEditRolesAndPermissionsUnderlyingCallsCount
|
||||||
|
} else {
|
||||||
|
var returnValue: Int? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = canOwnUserEditRolesAndPermissionsUnderlyingCallsCount
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
canOwnUserEditRolesAndPermissionsUnderlyingCallsCount = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
canOwnUserEditRolesAndPermissionsUnderlyingCallsCount = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var canOwnUserEditRolesAndPermissionsCalled: Bool {
|
||||||
|
return canOwnUserEditRolesAndPermissionsCallsCount > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var canOwnUserEditRolesAndPermissionsUnderlyingReturnValue: Bool!
|
||||||
|
var canOwnUserEditRolesAndPermissionsReturnValue: Bool! {
|
||||||
|
get {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
return canOwnUserEditRolesAndPermissionsUnderlyingReturnValue
|
||||||
|
} else {
|
||||||
|
var returnValue: Bool? = nil
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
returnValue = canOwnUserEditRolesAndPermissionsUnderlyingReturnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if Thread.isMainThread {
|
||||||
|
canOwnUserEditRolesAndPermissionsUnderlyingReturnValue = newValue
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.sync {
|
||||||
|
canOwnUserEditRolesAndPermissionsUnderlyingReturnValue = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var canOwnUserEditRolesAndPermissionsClosure: (() -> Bool)?
|
||||||
|
|
||||||
|
func canOwnUserEditRolesAndPermissions() -> Bool {
|
||||||
|
canOwnUserEditRolesAndPermissionsCallsCount += 1
|
||||||
|
if let canOwnUserEditRolesAndPermissionsClosure = canOwnUserEditRolesAndPermissionsClosure {
|
||||||
|
return canOwnUserEditRolesAndPermissionsClosure()
|
||||||
|
} else {
|
||||||
|
return canOwnUserEditRolesAndPermissionsReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
//MARK: - canUser
|
//MARK: - canUser
|
||||||
|
|
||||||
var canUserUserIDSendMessageUnderlyingCallsCount = 0
|
var canUserUserIDSendMessageUnderlyingCallsCount = 0
|
||||||
|
|||||||
@@ -116,12 +116,8 @@ extension JoinedRoomProxyMock {
|
|||||||
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role ?? .user != .user
|
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role ?? .user != .user
|
||||||
}
|
}
|
||||||
|
|
||||||
powerLevelsProxyMock.suggestedRoleForUserClosure = { [weak self] userID in
|
powerLevelsProxyMock.canOwnUserEditRolesAndPermissionsClosure = { [weak self] in
|
||||||
guard let member = self?.membersPublisher.value.first(where: { $0.userID == userID }) else {
|
self?.membersPublisher.value.first { $0.userID == configuration.ownUserID }?.role.isAdminOrHigher ?? false
|
||||||
return .user
|
|
||||||
}
|
|
||||||
|
|
||||||
return member.role
|
|
||||||
}
|
}
|
||||||
|
|
||||||
powerLevelsReturnValue = .success(powerLevelsProxyMock)
|
powerLevelsReturnValue = .success(powerLevelsProxyMock)
|
||||||
|
|||||||
@@ -120,6 +120,22 @@ extension RoomMemberProxyMock {
|
|||||||
role: .administrator))
|
role: .administrator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var mockCreator: RoomMemberProxyMock {
|
||||||
|
RoomMemberProxyMock(with: .init(userID: "@creator:matrix.org",
|
||||||
|
displayName: "God",
|
||||||
|
membership: .join,
|
||||||
|
powerLevel: .infinite,
|
||||||
|
role: .creator))
|
||||||
|
}
|
||||||
|
|
||||||
|
static var mockOwner: RoomMemberProxyMock {
|
||||||
|
RoomMemberProxyMock(with: .init(userID: "@owner:matrix.org",
|
||||||
|
displayName: "Guinevere",
|
||||||
|
membership: .join,
|
||||||
|
powerLevel: .value(150),
|
||||||
|
role: .administrator))
|
||||||
|
}
|
||||||
|
|
||||||
static var mockModerator: RoomMemberProxyMock {
|
static var mockModerator: RoomMemberProxyMock {
|
||||||
RoomMemberProxyMock(with: .init(userID: "@mod:matrix.org",
|
RoomMemberProxyMock(with: .init(userID: "@mod:matrix.org",
|
||||||
displayName: "Merlin",
|
displayName: "Merlin",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ struct RoomPowerLevelsProxyMockConfiguration {
|
|||||||
var canUserTriggerRoomNotification = false
|
var canUserTriggerRoomNotification = false
|
||||||
var canUserPin = true
|
var canUserPin = true
|
||||||
var canUserJoinCall = true
|
var canUserJoinCall = true
|
||||||
|
var canUserEditRoomsAndPermissions = true
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RoomPowerLevelsProxyMock {
|
extension RoomPowerLevelsProxyMock {
|
||||||
@@ -25,9 +26,7 @@ extension RoomPowerLevelsProxyMock {
|
|||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
underlyingValues = RoomPowerLevelsValues.mock
|
underlyingValues = RoomPowerLevelsValues.mock
|
||||||
|
|
||||||
suggestedRoleForUserReturnValue = .administrator
|
|
||||||
|
|
||||||
canOwnUserSendMessageReturnValue = configuration.canUserSendMessage
|
canOwnUserSendMessageReturnValue = configuration.canUserSendMessage
|
||||||
canOwnUserSendStateEventReturnValue = configuration.canUserSendState
|
canOwnUserSendStateEventReturnValue = configuration.canUserSendState
|
||||||
canOwnUserInviteReturnValue = configuration.canUserInvite
|
canOwnUserInviteReturnValue = configuration.canUserInvite
|
||||||
@@ -38,6 +37,7 @@ extension RoomPowerLevelsProxyMock {
|
|||||||
canOwnUserTriggerRoomNotificationReturnValue = configuration.canUserTriggerRoomNotification
|
canOwnUserTriggerRoomNotificationReturnValue = configuration.canUserTriggerRoomNotification
|
||||||
canOwnUserPinOrUnpinReturnValue = configuration.canUserPin
|
canOwnUserPinOrUnpinReturnValue = configuration.canUserPin
|
||||||
canOwnUserJoinCallReturnValue = configuration.canUserJoinCall
|
canOwnUserJoinCallReturnValue = configuration.canUserJoinCall
|
||||||
|
canOwnUserEditRolesAndPermissionsReturnValue = configuration.canUserEditRoomsAndPermissions
|
||||||
|
|
||||||
canUserUserIDSendMessageReturnValue = .success(configuration.canUserSendMessage)
|
canUserUserIDSendMessageReturnValue = .success(configuration.canUserSendMessage)
|
||||||
canUserUserIDSendStateEventReturnValue = .success(configuration.canUserSendState)
|
canUserUserIDSendStateEventReturnValue = .success(configuration.canUserSendState)
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ struct RoomChangeRolesScreenViewState: BindableState {
|
|||||||
/// The screen's title.
|
/// The screen's title.
|
||||||
var title: String {
|
var title: String {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .administrator:
|
case .creator, .owner, .administrator:
|
||||||
|
// TODO: Handle the creator permissions change
|
||||||
L10n.screenRoomChangeRoleAdministratorsTitle
|
L10n.screenRoomChangeRoleAdministratorsTitle
|
||||||
case .moderator:
|
case .moderator:
|
||||||
L10n.screenRoomChangeRoleModeratorsTitle
|
L10n.screenRoomChangeRoleModeratorsTitle
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class RoomChangeRolesScreenViewModel: RoomChangeRolesScreenViewModelType, RoomCh
|
|||||||
case .demoteMember(let member):
|
case .demoteMember(let member):
|
||||||
demoteMember(member)
|
demoteMember(member)
|
||||||
case .save:
|
case .save:
|
||||||
if state.mode == .administrator, !state.membersToPromote.isEmpty {
|
if state.mode.isAdminOrHigher, !state.membersToPromote.isEmpty {
|
||||||
showPromotionWarning()
|
showPromotionWarning()
|
||||||
} else {
|
} else {
|
||||||
Task { await save() }
|
Task { await save() }
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ struct RoomChangeRolesScreenSection: View {
|
|||||||
isSelected: isMemberSelected(member)) {
|
isSelected: isMemberSelected(member)) {
|
||||||
context.send(viewAction: .toggleMember(member))
|
context.send(viewAction: .toggleMember(member))
|
||||||
}
|
}
|
||||||
.disabled(member.role == .administrator)
|
.disabled(member.role.isAdminOrHigher)
|
||||||
}
|
}
|
||||||
} header: {
|
} header: {
|
||||||
Text(title)
|
Text(title)
|
||||||
@@ -40,6 +40,6 @@ struct RoomChangeRolesScreenSection: View {
|
|||||||
|
|
||||||
private func isMemberSelected(_ member: RoomMemberDetails) -> Bool {
|
private func isMemberSelected(_ member: RoomMemberDetails) -> Bool {
|
||||||
// We always show administrators as selected, even on the moderators screen.
|
// We always show administrators as selected, even on the moderators screen.
|
||||||
member.role == .administrator || context.viewState.isMemberSelected(member)
|
member.role.isAdminOrHigher || context.viewState.isMemberSelected(member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
state.canKickUsers = powerLevels.canOwnUserKick()
|
state.canKickUsers = powerLevels.canOwnUserKick()
|
||||||
state.canBanUsers = powerLevels.canOwnUserBan()
|
state.canBanUsers = powerLevels.canOwnUserBan()
|
||||||
state.canJoinCall = powerLevels.canOwnUserJoinCall()
|
state.canJoinCall = powerLevels.canOwnUserJoinCall()
|
||||||
state.canEditRolesOrPermissions = powerLevels.suggestedRole(forUser: roomProxy.ownUserID) == .administrator
|
state.canEditRolesOrPermissions = powerLevels.canOwnUserEditRolesAndPermissions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,6 +168,8 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
.mockBob,
|
.mockBob,
|
||||||
.mockCharlie,
|
.mockCharlie,
|
||||||
mockAdmin,
|
mockAdmin,
|
||||||
|
.mockCreator,
|
||||||
|
.mockOwner,
|
||||||
.mockModerator
|
.mockModerator
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+2
@@ -55,6 +55,8 @@ struct RoomMembersListScreenMemberCell: View {
|
|||||||
|
|
||||||
var role: String? {
|
var role: String? {
|
||||||
switch listEntry.member.role {
|
switch listEntry.member.role {
|
||||||
|
case .creator, .owner:
|
||||||
|
L10n.screenRoomMemberListRoleOwner
|
||||||
case .administrator:
|
case .administrator:
|
||||||
L10n.screenRoomMemberListRoleAdministrator
|
L10n.screenRoomMemberListRoleAdministrator
|
||||||
case .moderator:
|
case .moderator:
|
||||||
|
|||||||
+2
-1
@@ -84,7 +84,8 @@ class RoomRolesAndPermissionsScreenViewModel: RoomRolesAndPermissionsScreenViewM
|
|||||||
// MARK: - Members
|
// MARK: - Members
|
||||||
|
|
||||||
private func updateMembers(_ members: [RoomMemberProxyProtocol]) {
|
private func updateMembers(_ members: [RoomMemberProxyProtocol]) {
|
||||||
state.administratorCount = members.filter { $0.role == .administrator && $0.isActive }.count
|
// TODO: Will probably be changed when we implement the owners list
|
||||||
|
state.administratorCount = members.filter { $0.role.isAdminOrHigher && $0.isActive }.count
|
||||||
state.moderatorCount = members.filter { $0.role == .moderator && $0.isActive }.count
|
state.moderatorCount = members.filter { $0.role == .moderator && $0.isActive }.count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import AnalyticsEvents
|
|||||||
extension AnalyticsEvent.RoomModeration.Role {
|
extension AnalyticsEvent.RoomModeration.Role {
|
||||||
init(role: RoomMemberDetails.Role) {
|
init(role: RoomMemberDetails.Role) {
|
||||||
switch role {
|
switch role {
|
||||||
case .administrator:
|
case .administrator, .creator, .owner:
|
||||||
|
// This probably needs to be updates
|
||||||
self = .Administrator
|
self = .Administrator
|
||||||
case .moderator:
|
case .moderator:
|
||||||
self = .Moderator
|
self = .Moderator
|
||||||
|
|||||||
@@ -19,7 +19,19 @@ struct RoomMemberDetails: Identifiable, Hashable {
|
|||||||
var isBanned: Bool
|
var isBanned: Bool
|
||||||
var isActive: 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 role: Role
|
||||||
let powerLevel: RoomPowerLevel
|
let powerLevel: RoomPowerLevel
|
||||||
|
|
||||||
@@ -39,18 +51,47 @@ extension RoomMemberDetails {
|
|||||||
isInvited = proxy.membership == .invite
|
isInvited = proxy.membership == .invite
|
||||||
isIgnored = proxy.isIgnored
|
isIgnored = proxy.isIgnored
|
||||||
isBanned = proxy.membership == .ban
|
isBanned = proxy.membership == .ban
|
||||||
role = .init(proxy.role)
|
role = .init(proxy.role, powerLevel: proxy.powerLevel)
|
||||||
powerLevel = proxy.powerLevel
|
powerLevel = proxy.powerLevel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RoomMemberDetails.Role {
|
extension RoomMemberDetails.Role {
|
||||||
init(_ role: RoomMemberRole) {
|
init(_ role: RoomMemberRole, powerLevel: RoomPowerLevel) {
|
||||||
self = switch role {
|
switch role {
|
||||||
// TODO: Implement creator role
|
case .creator:
|
||||||
case .creator, .administrator: .administrator
|
self = .creator
|
||||||
case .moderator: .moderator
|
case .administrator:
|
||||||
case .user: .user
|
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 {
|
extension RoomMemberDetails.Role {
|
||||||
init(powerLevelValue: Int64) {
|
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 {
|
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 {
|
} catch {
|
||||||
MXLog.error("Falied to convert power level value to role: \(error)")
|
MXLog.error("Falied to convert power level value to role: \(error)")
|
||||||
self.init(.user)
|
self = .user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rustRole: RoomMemberRole {
|
var rustRole: RoomMemberRole {
|
||||||
switch self {
|
switch self {
|
||||||
case .administrator:
|
case .creator:
|
||||||
|
.creator
|
||||||
|
case .administrator, .owner:
|
||||||
.administrator
|
.administrator
|
||||||
case .moderator:
|
case .moderator:
|
||||||
.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
|
/// 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.
|
/// NOTE: Do not use for comparison, use the true power level instead.
|
||||||
var powerLevelValue: Int64 {
|
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 {
|
do {
|
||||||
switch try suggestedPowerLevelForRole(role: rustRole) {
|
switch try suggestedPowerLevelForRole(role: rustRole) {
|
||||||
case .infinite:
|
case .infinite:
|
||||||
// Would be better if the SDK would return this, maybe a `suggestedPowerLevelValueForRole` function would solve the problem
|
fatalError("Impossible")
|
||||||
return 150
|
|
||||||
case .value(let value):
|
case .value(let value):
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ import MatrixRustSDK
|
|||||||
protocol RoomPowerLevelsProxyProtocol {
|
protocol RoomPowerLevelsProxyProtocol {
|
||||||
var values: RoomPowerLevelsValues { get }
|
var values: RoomPowerLevelsValues { get }
|
||||||
var userPowerLevels: [String: Int64] { get }
|
var userPowerLevels: [String: Int64] { get }
|
||||||
|
|
||||||
func suggestedRole(forUser userID: String) -> RoomMemberRole
|
|
||||||
|
|
||||||
func canOwnUser(sendMessage messageType: MessageLikeEventType) -> Bool
|
func canOwnUser(sendMessage messageType: MessageLikeEventType) -> Bool
|
||||||
func canOwnUser(sendStateEvent event: StateEventType) -> Bool
|
func canOwnUser(sendStateEvent event: StateEventType) -> Bool
|
||||||
func canOwnUserInvite() -> Bool
|
func canOwnUserInvite() -> Bool
|
||||||
@@ -24,6 +22,7 @@ protocol RoomPowerLevelsProxyProtocol {
|
|||||||
func canOwnUserTriggerRoomNotification() -> Bool
|
func canOwnUserTriggerRoomNotification() -> Bool
|
||||||
func canOwnUserPinOrUnpin() -> Bool
|
func canOwnUserPinOrUnpin() -> Bool
|
||||||
func canOwnUserJoinCall() -> Bool
|
func canOwnUserJoinCall() -> Bool
|
||||||
|
func canOwnUserEditRolesAndPermissions() -> Bool
|
||||||
|
|
||||||
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError>
|
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError>
|
||||||
func canUser(userID: String, sendStateEvent event: StateEventType) -> Result<Bool, RoomProxyError>
|
func canUser(userID: String, sendStateEvent event: StateEventType) -> Result<Bool, RoomProxyError>
|
||||||
|
|||||||
@@ -26,16 +26,6 @@ struct RoomPowerLevelsProxy: RoomPowerLevelsProxyProtocol {
|
|||||||
powerLevels.userPowerLevels()
|
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 {
|
func canOwnUser(sendMessage messageType: MessageLikeEventType) -> Bool {
|
||||||
powerLevels.canOwnUserSendMessage(message: messageType)
|
powerLevels.canOwnUserSendMessage(message: messageType)
|
||||||
}
|
}
|
||||||
@@ -76,6 +66,10 @@ struct RoomPowerLevelsProxy: RoomPowerLevelsProxyProtocol {
|
|||||||
powerLevels.canOwnUserSendState(stateEvent: .callMember)
|
powerLevels.canOwnUserSendState(stateEvent: .callMember)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canOwnUserEditRolesAndPermissions() -> Bool {
|
||||||
|
powerLevels.canOwnUserSendState(stateEvent: .roomPowerLevels)
|
||||||
|
}
|
||||||
|
|
||||||
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError> {
|
func canUser(userID: String, sendMessage messageType: MessageLikeEventType) -> Result<Bool, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
return try .success(powerLevels.canUserSendMessage(userId: userID, message: messageType))
|
return try .success(powerLevels.canUserSendMessage(userId: userID, message: messageType))
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:fe572408dfab096b40fe832f3af04825604aa128f672feaac239e7a4f7b10d73
|
oid sha256:de7dd0a25278cb3d850bb17745eabf73c82bb8de714de3176176ef0205cfda26
|
||||||
size 134463
|
size 155431
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:11163c9d94a5c0e3d1f1d725eb2c886cb243d4e59564c80aebdf5325bd335a54
|
oid sha256:a720efc67edbb7eb11b0a2f9bd85850729937f99bb077b0d08f7598484d9c6a7
|
||||||
size 143380
|
size 167197
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:a37767187891e271c7ebb6ec62f8251022d7f07eefdebd7a3b883f95b6a6c877
|
oid sha256:6ce76f7eb6367b8ac122d77017907b08052a2d1bc73af12fcf5c5826a2de83f4
|
||||||
size 84829
|
size 101372
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:1db62e88774b134efce48a06df934aab020cff16f1e0c1c2729edc036116a59c
|
oid sha256:36f0da3b02ad88aef6045288f2520866de1ca2fece50c302a3e79a97c414dab1
|
||||||
size 94434
|
size 112674
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:21ded3dc1828d99325b5bcf85eda0be6daee71fc6571344cccdffa3d5d93437e
|
oid sha256:536c5e08b44cbe6d3b9d1c2e6ec8b32d919f911ad5af09cf59d29a6985092d19
|
||||||
size 137744
|
size 158614
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:39ffdb0635318f13f96ee4b0939b1b91804ddae5932e872cd044ca78f8c4b669
|
oid sha256:ea481ed68ee357f10b6f1777addad6d927c5de71f75862c7859ead98d6445ece
|
||||||
size 145858
|
size 169472
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:f07ca02c19c528cc8de2bc496203dd439452290f2fd71f71af5f18d3988de12d
|
oid sha256:d163845228de4646f5ed876b5c44850a9f24a18a4e3f0d87c206b13e78e3b199
|
||||||
size 87192
|
size 104634
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:67f6d58d14feac246ed347c515dcdd4e63fadf51dfab22c6d8332f60467a0f17
|
oid sha256:df3c4dee3447725f3dd2cc5665a1ecde0a7816625eab674f39909d5578ebe83b
|
||||||
size 97161
|
size 116454
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:adb9a4c8585acb6bd4841723299c662dbb0285b8a81ee7b30042aebc0be8d163
|
oid sha256:02637fcc5d6a92beb9bdd84e2ad1018f4021639bb03a159e7e940c5f36ab9093
|
||||||
size 127054
|
size 147956
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9be1a0c6030ef1ff21c83faf99f304cf755a07bc04294f4ccae05b8365c0485a
|
oid sha256:c4964d2d39a3e8ede1c817d2b771bd12fa28e4678a9df81b34d509cb922e3f38
|
||||||
size 135050
|
size 158785
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:a90905ef38f880e2c67368f9ccfc6e4e811c8c7b69b4cccd39672435abe5f6a5
|
oid sha256:0a52e8ed7e8a131fbd5a1453109a7741607a20eb9a06be07bc3a49a1363d05d7
|
||||||
size 78999
|
size 94960
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e22ae73b0ff3730dce2f6becc460ec5d07be3262cd69d74d7f3f30ca8f8cd23d
|
oid sha256:b9781146ec5417aac27600db5e77f01002c454c58e3d1905ebf63d0e19710b56
|
||||||
size 87347
|
size 105019
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class RoomMembersListScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
// When tapping on another administrator in the list.
|
// When tapping on another administrator in the list.
|
||||||
deferred = deferFulfillment(context.$viewState) { $0.bindings.manageMemeberViewModel != nil }
|
deferred = deferFulfillment(context.$viewState) { $0.bindings.manageMemeberViewModel != nil }
|
||||||
guard let admin = viewModel.state.visibleJoinedMembers.first(where: { $0.member.role == .administrator && $0.member.id != RoomMemberProxyMock.mockMe.userID })?.member else {
|
guard let admin = viewModel.state.visibleJoinedMembers.first(where: { $0.member.role.isAdminOrHigher && $0.member.id != RoomMemberProxyMock.mockMe.userID })?.member else {
|
||||||
XCTFail("Expected to find another admin.")
|
XCTFail("Expected to find another admin.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user