mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-06 12:28:29 +00:00
Update the SDK and handle breaking changes. (#2527)
This commit is contained in:
@@ -7044,7 +7044,7 @@
|
|||||||
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
repositoryURL = "https://github.com/matrix-org/matrix-rust-components-swift";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = 1.1.44;
|
version = 1.1.45;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {
|
821C67C9A7F8CC3FD41B28B4 /* XCRemoteSwiftPackageReference "emojibase-bindings" */ = {
|
||||||
|
|||||||
@@ -130,8 +130,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
|
"location" : "https://github.com/matrix-org/matrix-rust-components-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "c8d0dd3b7756584276ffb95ffc261aada654e0fa",
|
"revision" : "55425c708ba6377ef319f85f6f70c7caf2187368",
|
||||||
"version" : "1.1.44"
|
"version" : "1.1.45"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -256,8 +256,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (.roomDetails, .dismissRoom, .initial):
|
case (.roomDetails, .dismissRoom, .initial):
|
||||||
dismissRoom(animated: animated)
|
dismissRoom(animated: animated)
|
||||||
|
|
||||||
case (.roomDetails, .presentRoomDetailsEditScreen(let accountOwner), .roomDetailsEditScreen):
|
case (.roomDetails, .presentRoomDetailsEditScreen, .roomDetailsEditScreen):
|
||||||
presentRoomDetailsEditScreen(accountOwner: accountOwner.value)
|
presentRoomDetailsEditScreen()
|
||||||
case (.roomDetailsEditScreen, .dismissRoomDetailsEditScreen, .roomDetails):
|
case (.roomDetailsEditScreen, .dismissRoomDetailsEditScreen, .roomDetails):
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -520,8 +520,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = RoomDetailsScreenCoordinatorParameters(accountUserID: userSession.userID,
|
let params = RoomDetailsScreenCoordinatorParameters(roomProxy: roomProxy,
|
||||||
roomProxy: roomProxy,
|
clientProxy: userSession.clientProxy,
|
||||||
mediaProvider: userSession.mediaProvider,
|
mediaProvider: userSession.mediaProvider,
|
||||||
analyticsService: analytics,
|
analyticsService: analytics,
|
||||||
userIndicatorController: userIndicatorController,
|
userIndicatorController: userIndicatorController,
|
||||||
@@ -537,8 +537,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
dismissRoom(animated: animated)
|
dismissRoom(animated: animated)
|
||||||
case .presentRoomMembersList:
|
case .presentRoomMembersList:
|
||||||
stateMachine.tryEvent(.presentRoomMembersList)
|
stateMachine.tryEvent(.presentRoomMembersList)
|
||||||
case .presentRoomDetailsEditScreen(let accountOwner):
|
case .presentRoomDetailsEditScreen:
|
||||||
stateMachine.tryEvent(.presentRoomDetailsEditScreen(accountOwner: .init(value: accountOwner)))
|
stateMachine.tryEvent(.presentRoomDetailsEditScreen)
|
||||||
case .presentNotificationSettingsScreen:
|
case .presentNotificationSettingsScreen:
|
||||||
stateMachine.tryEvent(.presentNotificationSettingsScreen)
|
stateMachine.tryEvent(.presentNotificationSettingsScreen)
|
||||||
case .presentInviteUsersScreen:
|
case .presentInviteUsersScreen:
|
||||||
@@ -600,17 +600,16 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol) {
|
private func presentRoomDetailsEditScreen() {
|
||||||
guard let roomProxy else {
|
guard let roomProxy else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
|
||||||
let stackCoordinator = NavigationStackCoordinator()
|
let stackCoordinator = NavigationStackCoordinator()
|
||||||
|
|
||||||
let roomDetailsEditParameters = RoomDetailsEditScreenCoordinatorParameters(accountOwner: accountOwner,
|
let roomDetailsEditParameters = RoomDetailsEditScreenCoordinatorParameters(roomProxy: roomProxy,
|
||||||
mediaProvider: userSession.mediaProvider,
|
mediaProvider: userSession.mediaProvider,
|
||||||
navigationStackCoordinator: stackCoordinator,
|
navigationStackCoordinator: stackCoordinator,
|
||||||
roomProxy: roomProxy,
|
|
||||||
userIndicatorController: userIndicatorController,
|
userIndicatorController: userIndicatorController,
|
||||||
orientationManager: orientationManager)
|
orientationManager: orientationManager)
|
||||||
let roomDetailsEditCoordinator = RoomDetailsEditScreenCoordinator(parameters: roomDetailsEditParameters)
|
let roomDetailsEditCoordinator = RoomDetailsEditScreenCoordinator(parameters: roomDetailsEditParameters)
|
||||||
@@ -639,6 +638,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
let parameters = ReportContentScreenCoordinatorParameters(eventID: eventID,
|
let parameters = ReportContentScreenCoordinatorParameters(eventID: eventID,
|
||||||
senderID: senderID,
|
senderID: senderID,
|
||||||
roomProxy: roomProxy,
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: userSession.clientProxy,
|
||||||
userIndicatorController: userIndicatorController)
|
userIndicatorController: userIndicatorController)
|
||||||
let coordinator = ReportContentScreenCoordinator(parameters: parameters)
|
let coordinator = ReportContentScreenCoordinator(parameters: parameters)
|
||||||
|
|
||||||
@@ -928,8 +928,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = RoomMemberDetailsScreenCoordinatorParameters(roomProxy: roomProxy,
|
let params = RoomMemberDetailsScreenCoordinatorParameters(userID: userID,
|
||||||
userID: userID,
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: userSession.clientProxy,
|
||||||
mediaProvider: userSession.mediaProvider,
|
mediaProvider: userSession.mediaProvider,
|
||||||
userIndicatorController: userIndicatorController)
|
userIndicatorController: userIndicatorController)
|
||||||
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: params)
|
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: params)
|
||||||
@@ -1205,7 +1206,7 @@ private extension RoomFlowCoordinator {
|
|||||||
case presentRoomDetails(roomID: String)
|
case presentRoomDetails(roomID: String)
|
||||||
case dismissRoomDetails
|
case dismissRoomDetails
|
||||||
|
|
||||||
case presentRoomDetailsEditScreen(accountOwner: HashableRoomMemberWrapper)
|
case presentRoomDetailsEditScreen
|
||||||
case dismissRoomDetailsEditScreen
|
case dismissRoomDetailsEditScreen
|
||||||
|
|
||||||
case presentNotificationSettingsScreen
|
case presentNotificationSettingsScreen
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import Combine
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct ClientProxyMockConfiguration {
|
struct ClientProxyMockConfiguration {
|
||||||
let userID: String
|
var userID: String = RoomMemberProxyMock.mockMe.userID
|
||||||
var deviceID: String?
|
var deviceID: String?
|
||||||
var roomSummaryProvider: RoomSummaryProviderProtocol? = RoomSummaryProviderMock(.init())
|
var roomSummaryProvider: RoomSummaryProviderProtocol? = RoomSummaryProviderMock(.init())
|
||||||
}
|
}
|
||||||
@@ -62,8 +62,8 @@ extension ClientProxyMock {
|
|||||||
searchUsersSearchTermLimitReturnValue = .success(.init(results: [], limited: false))
|
searchUsersSearchTermLimitReturnValue = .success(.init(results: [], limited: false))
|
||||||
profileForReturnValue = .success(.init(userID: "@a:b.com", displayName: "Some user"))
|
profileForReturnValue = .success(.init(userID: "@a:b.com", displayName: "Some user"))
|
||||||
sessionVerificationControllerProxyReturnValue = .failure(.failedRetrievingSessionVerificationController)
|
sessionVerificationControllerProxyReturnValue = .failure(.failedRetrievingSessionVerificationController)
|
||||||
ignoreUserReturnValue = .failure(.failedIgnoringUser)
|
ignoreUserReturnValue = .success(())
|
||||||
unignoreUserReturnValue = .failure(.failedUnignoringUser)
|
unignoreUserReturnValue = .success(())
|
||||||
|
|
||||||
loadMediaContentForSourceThrowableError = ClientProxyError.failedLoadingMedia
|
loadMediaContentForSourceThrowableError = ClientProxyError.failedLoadingMedia
|
||||||
loadMediaThumbnailForSourceWidthHeightThrowableError = ClientProxyError.failedLoadingMedia
|
loadMediaThumbnailForSourceWidthHeightThrowableError = ClientProxyError.failedLoadingMedia
|
||||||
|
|||||||
@@ -2253,11 +2253,6 @@ class RoomMemberProxyMock: RoomMemberProxyProtocol {
|
|||||||
set(value) { underlyingMembership = value }
|
set(value) { underlyingMembership = value }
|
||||||
}
|
}
|
||||||
var underlyingMembership: MembershipState!
|
var underlyingMembership: MembershipState!
|
||||||
var isAccountOwner: Bool {
|
|
||||||
get { return underlyingIsAccountOwner }
|
|
||||||
set(value) { underlyingIsAccountOwner = value }
|
|
||||||
}
|
|
||||||
var underlyingIsAccountOwner: Bool!
|
|
||||||
var isIgnored: Bool {
|
var isIgnored: Bool {
|
||||||
get { return underlyingIsIgnored }
|
get { return underlyingIsIgnored }
|
||||||
set(value) { underlyingIsIgnored = value }
|
set(value) { underlyingIsIgnored = value }
|
||||||
@@ -2273,77 +2268,7 @@ class RoomMemberProxyMock: RoomMemberProxyProtocol {
|
|||||||
set(value) { underlyingRole = value }
|
set(value) { underlyingRole = value }
|
||||||
}
|
}
|
||||||
var underlyingRole: RoomMemberRole!
|
var underlyingRole: RoomMemberRole!
|
||||||
var canInviteUsers: Bool {
|
|
||||||
get { return underlyingCanInviteUsers }
|
|
||||||
set(value) { underlyingCanInviteUsers = value }
|
|
||||||
}
|
|
||||||
var underlyingCanInviteUsers: Bool!
|
|
||||||
var canKickUsers: Bool {
|
|
||||||
get { return underlyingCanKickUsers }
|
|
||||||
set(value) { underlyingCanKickUsers = value }
|
|
||||||
}
|
|
||||||
var underlyingCanKickUsers: Bool!
|
|
||||||
var canBanUsers: Bool {
|
|
||||||
get { return underlyingCanBanUsers }
|
|
||||||
set(value) { underlyingCanBanUsers = value }
|
|
||||||
}
|
|
||||||
var underlyingCanBanUsers: Bool!
|
|
||||||
|
|
||||||
//MARK: - ignoreUser
|
|
||||||
|
|
||||||
var ignoreUserCallsCount = 0
|
|
||||||
var ignoreUserCalled: Bool {
|
|
||||||
return ignoreUserCallsCount > 0
|
|
||||||
}
|
|
||||||
var ignoreUserReturnValue: Result<Void, RoomMemberProxyError>!
|
|
||||||
var ignoreUserClosure: (() async -> Result<Void, RoomMemberProxyError>)?
|
|
||||||
|
|
||||||
func ignoreUser() async -> Result<Void, RoomMemberProxyError> {
|
|
||||||
ignoreUserCallsCount += 1
|
|
||||||
if let ignoreUserClosure = ignoreUserClosure {
|
|
||||||
return await ignoreUserClosure()
|
|
||||||
} else {
|
|
||||||
return ignoreUserReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//MARK: - unignoreUser
|
|
||||||
|
|
||||||
var unignoreUserCallsCount = 0
|
|
||||||
var unignoreUserCalled: Bool {
|
|
||||||
return unignoreUserCallsCount > 0
|
|
||||||
}
|
|
||||||
var unignoreUserReturnValue: Result<Void, RoomMemberProxyError>!
|
|
||||||
var unignoreUserClosure: (() async -> Result<Void, RoomMemberProxyError>)?
|
|
||||||
|
|
||||||
func unignoreUser() async -> Result<Void, RoomMemberProxyError> {
|
|
||||||
unignoreUserCallsCount += 1
|
|
||||||
if let unignoreUserClosure = unignoreUserClosure {
|
|
||||||
return await unignoreUserClosure()
|
|
||||||
} else {
|
|
||||||
return unignoreUserReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//MARK: - canSendStateEvent
|
|
||||||
|
|
||||||
var canSendStateEventTypeCallsCount = 0
|
|
||||||
var canSendStateEventTypeCalled: Bool {
|
|
||||||
return canSendStateEventTypeCallsCount > 0
|
|
||||||
}
|
|
||||||
var canSendStateEventTypeReceivedType: StateEventType?
|
|
||||||
var canSendStateEventTypeReceivedInvocations: [StateEventType] = []
|
|
||||||
var canSendStateEventTypeReturnValue: Bool!
|
|
||||||
var canSendStateEventTypeClosure: ((StateEventType) -> Bool)?
|
|
||||||
|
|
||||||
func canSendStateEvent(type: StateEventType) -> Bool {
|
|
||||||
canSendStateEventTypeCallsCount += 1
|
|
||||||
canSendStateEventTypeReceivedType = type
|
|
||||||
canSendStateEventTypeReceivedInvocations.append(type)
|
|
||||||
if let canSendStateEventTypeClosure = canSendStateEventTypeClosure {
|
|
||||||
return canSendStateEventTypeClosure(type)
|
|
||||||
} else {
|
|
||||||
return canSendStateEventTypeReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol {
|
class RoomNotificationSettingsProxyMock: RoomNotificationSettingsProxyProtocol {
|
||||||
var mode: RoomNotificationModeProxy {
|
var mode: RoomNotificationModeProxy {
|
||||||
@@ -2517,27 +2442,6 @@ class RoomProxyMock: RoomProxyProtocol {
|
|||||||
return reportContentReasonReturnValue
|
return reportContentReasonReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - ignoreUser
|
|
||||||
|
|
||||||
var ignoreUserCallsCount = 0
|
|
||||||
var ignoreUserCalled: Bool {
|
|
||||||
return ignoreUserCallsCount > 0
|
|
||||||
}
|
|
||||||
var ignoreUserReceivedUserID: String?
|
|
||||||
var ignoreUserReceivedInvocations: [String] = []
|
|
||||||
var ignoreUserReturnValue: Result<Void, RoomProxyError>!
|
|
||||||
var ignoreUserClosure: ((String) async -> Result<Void, RoomProxyError>)?
|
|
||||||
|
|
||||||
func ignoreUser(_ userID: String) async -> Result<Void, RoomProxyError> {
|
|
||||||
ignoreUserCallsCount += 1
|
|
||||||
ignoreUserReceivedUserID = userID
|
|
||||||
ignoreUserReceivedInvocations.append(userID)
|
|
||||||
if let ignoreUserClosure = ignoreUserClosure {
|
|
||||||
return await ignoreUserClosure(userID)
|
|
||||||
} else {
|
|
||||||
return ignoreUserReturnValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//MARK: - leaveRoom
|
//MARK: - leaveRoom
|
||||||
|
|
||||||
var leaveRoomCallsCount = 0
|
var leaveRoomCallsCount = 0
|
||||||
@@ -2846,6 +2750,48 @@ class RoomProxyMock: RoomProxyProtocol {
|
|||||||
return applyPowerLevelChangesReturnValue
|
return applyPowerLevelChangesReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//MARK: - canUser
|
||||||
|
|
||||||
|
var canUserUserIDSendStateEventCallsCount = 0
|
||||||
|
var canUserUserIDSendStateEventCalled: Bool {
|
||||||
|
return canUserUserIDSendStateEventCallsCount > 0
|
||||||
|
}
|
||||||
|
var canUserUserIDSendStateEventReceivedArguments: (userID: String, event: StateEventType)?
|
||||||
|
var canUserUserIDSendStateEventReceivedInvocations: [(userID: String, event: StateEventType)] = []
|
||||||
|
var canUserUserIDSendStateEventReturnValue: Result<Bool, RoomProxyError>!
|
||||||
|
var canUserUserIDSendStateEventClosure: ((String, StateEventType) async -> Result<Bool, RoomProxyError>)?
|
||||||
|
|
||||||
|
func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result<Bool, RoomProxyError> {
|
||||||
|
canUserUserIDSendStateEventCallsCount += 1
|
||||||
|
canUserUserIDSendStateEventReceivedArguments = (userID: userID, event: event)
|
||||||
|
canUserUserIDSendStateEventReceivedInvocations.append((userID: userID, event: event))
|
||||||
|
if let canUserUserIDSendStateEventClosure = canUserUserIDSendStateEventClosure {
|
||||||
|
return await canUserUserIDSendStateEventClosure(userID, event)
|
||||||
|
} else {
|
||||||
|
return canUserUserIDSendStateEventReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - canUserInvite
|
||||||
|
|
||||||
|
var canUserInviteUserIDCallsCount = 0
|
||||||
|
var canUserInviteUserIDCalled: Bool {
|
||||||
|
return canUserInviteUserIDCallsCount > 0
|
||||||
|
}
|
||||||
|
var canUserInviteUserIDReceivedUserID: String?
|
||||||
|
var canUserInviteUserIDReceivedInvocations: [String] = []
|
||||||
|
var canUserInviteUserIDReturnValue: Result<Bool, RoomProxyError>!
|
||||||
|
var canUserInviteUserIDClosure: ((String) async -> Result<Bool, RoomProxyError>)?
|
||||||
|
|
||||||
|
func canUserInvite(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
|
canUserInviteUserIDCallsCount += 1
|
||||||
|
canUserInviteUserIDReceivedUserID = userID
|
||||||
|
canUserInviteUserIDReceivedInvocations.append(userID)
|
||||||
|
if let canUserInviteUserIDClosure = canUserInviteUserIDClosure {
|
||||||
|
return await canUserInviteUserIDClosure(userID)
|
||||||
|
} else {
|
||||||
|
return canUserInviteUserIDReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
//MARK: - canUserRedactOther
|
//MARK: - canUserRedactOther
|
||||||
|
|
||||||
var canUserRedactOtherUserIDCallsCount = 0
|
var canUserRedactOtherUserIDCallsCount = 0
|
||||||
@@ -2888,6 +2834,48 @@ class RoomProxyMock: RoomProxyProtocol {
|
|||||||
return canUserRedactOwnUserIDReturnValue
|
return canUserRedactOwnUserIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//MARK: - canUserKick
|
||||||
|
|
||||||
|
var canUserKickUserIDCallsCount = 0
|
||||||
|
var canUserKickUserIDCalled: Bool {
|
||||||
|
return canUserKickUserIDCallsCount > 0
|
||||||
|
}
|
||||||
|
var canUserKickUserIDReceivedUserID: String?
|
||||||
|
var canUserKickUserIDReceivedInvocations: [String] = []
|
||||||
|
var canUserKickUserIDReturnValue: Result<Bool, RoomProxyError>!
|
||||||
|
var canUserKickUserIDClosure: ((String) async -> Result<Bool, RoomProxyError>)?
|
||||||
|
|
||||||
|
func canUserKick(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
|
canUserKickUserIDCallsCount += 1
|
||||||
|
canUserKickUserIDReceivedUserID = userID
|
||||||
|
canUserKickUserIDReceivedInvocations.append(userID)
|
||||||
|
if let canUserKickUserIDClosure = canUserKickUserIDClosure {
|
||||||
|
return await canUserKickUserIDClosure(userID)
|
||||||
|
} else {
|
||||||
|
return canUserKickUserIDReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//MARK: - canUserBan
|
||||||
|
|
||||||
|
var canUserBanUserIDCallsCount = 0
|
||||||
|
var canUserBanUserIDCalled: Bool {
|
||||||
|
return canUserBanUserIDCallsCount > 0
|
||||||
|
}
|
||||||
|
var canUserBanUserIDReceivedUserID: String?
|
||||||
|
var canUserBanUserIDReceivedInvocations: [String] = []
|
||||||
|
var canUserBanUserIDReturnValue: Result<Bool, RoomProxyError>!
|
||||||
|
var canUserBanUserIDClosure: ((String) async -> Result<Bool, RoomProxyError>)?
|
||||||
|
|
||||||
|
func canUserBan(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
|
canUserBanUserIDCallsCount += 1
|
||||||
|
canUserBanUserIDReceivedUserID = userID
|
||||||
|
canUserBanUserIDReceivedInvocations.append(userID)
|
||||||
|
if let canUserBanUserIDClosure = canUserBanUserIDClosure {
|
||||||
|
return await canUserBanUserIDClosure(userID)
|
||||||
|
} else {
|
||||||
|
return canUserBanUserIDReturnValue
|
||||||
|
}
|
||||||
|
}
|
||||||
//MARK: - canUserTriggerRoomNotification
|
//MARK: - canUserTriggerRoomNotification
|
||||||
|
|
||||||
var canUserTriggerRoomNotificationUserIDCallsCount = 0
|
var canUserTriggerRoomNotificationUserIDCallsCount = 0
|
||||||
|
|||||||
@@ -21,15 +21,12 @@ struct RoomMemberProxyMockConfiguration {
|
|||||||
var userID: String
|
var userID: String
|
||||||
var displayName: String?
|
var displayName: String?
|
||||||
var avatarURL: URL?
|
var avatarURL: URL?
|
||||||
|
|
||||||
var membership: MembershipState
|
var membership: MembershipState
|
||||||
var isAccountOwner = false
|
|
||||||
var isIgnored = false
|
var isIgnored = false
|
||||||
|
|
||||||
var powerLevel = 0
|
var powerLevel = 0
|
||||||
var role = RoomMemberRole.user
|
var role = RoomMemberRole.user
|
||||||
var canInviteUsers = false
|
|
||||||
var canKickUsers = false
|
|
||||||
var canBanUsers = false
|
|
||||||
var canSendStateEvent: (StateEventType) -> Bool = { _ in true }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RoomMemberProxyMock {
|
extension RoomMemberProxyMock {
|
||||||
@@ -38,15 +35,12 @@ extension RoomMemberProxyMock {
|
|||||||
userID = configuration.userID
|
userID = configuration.userID
|
||||||
displayName = configuration.displayName
|
displayName = configuration.displayName
|
||||||
avatarURL = configuration.avatarURL
|
avatarURL = configuration.avatarURL
|
||||||
|
|
||||||
membership = configuration.membership
|
membership = configuration.membership
|
||||||
isAccountOwner = configuration.isAccountOwner
|
|
||||||
isIgnored = configuration.isIgnored
|
isIgnored = configuration.isIgnored
|
||||||
|
|
||||||
powerLevel = configuration.powerLevel
|
powerLevel = configuration.powerLevel
|
||||||
role = configuration.role
|
role = configuration.role
|
||||||
canInviteUsers = configuration.canInviteUsers
|
|
||||||
canKickUsers = configuration.canKickUsers
|
|
||||||
canBanUsers = configuration.canBanUsers
|
|
||||||
canSendStateEventTypeClosure = configuration.canSendStateEvent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mocks
|
// Mocks
|
||||||
@@ -54,9 +48,7 @@ extension RoomMemberProxyMock {
|
|||||||
RoomMemberProxyMock(with: .init(userID: "@me:matrix.org",
|
RoomMemberProxyMock(with: .init(userID: "@me:matrix.org",
|
||||||
displayName: "Me",
|
displayName: "Me",
|
||||||
avatarURL: URL.picturesDirectory,
|
avatarURL: URL.picturesDirectory,
|
||||||
membership: .join,
|
membership: .join))
|
||||||
isAccountOwner: true,
|
|
||||||
canInviteUsers: true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static var mockMeAdmin: RoomMemberProxyMock {
|
static var mockMeAdmin: RoomMemberProxyMock {
|
||||||
@@ -64,12 +56,8 @@ extension RoomMemberProxyMock {
|
|||||||
displayName: "Me admin",
|
displayName: "Me admin",
|
||||||
avatarURL: URL.picturesDirectory,
|
avatarURL: URL.picturesDirectory,
|
||||||
membership: .join,
|
membership: .join,
|
||||||
isAccountOwner: true,
|
|
||||||
powerLevel: 100,
|
powerLevel: 100,
|
||||||
role: .administrator,
|
role: .administrator))
|
||||||
canInviteUsers: true,
|
|
||||||
canKickUsers: true,
|
|
||||||
canBanUsers: true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static var mockAlice: RoomMemberProxyMock {
|
static var mockAlice: RoomMemberProxyMock {
|
||||||
@@ -117,15 +105,6 @@ extension RoomMemberProxyMock {
|
|||||||
isIgnored: true))
|
isIgnored: true))
|
||||||
}
|
}
|
||||||
|
|
||||||
static func mockOwner(allowedStateEvents: [StateEventType], canInviteUsers: Bool = true) -> RoomMemberProxyMock {
|
|
||||||
RoomMemberProxyMock(with: .init(userID: "@foo:some.org",
|
|
||||||
displayName: "User owner",
|
|
||||||
membership: .join,
|
|
||||||
isAccountOwner: true,
|
|
||||||
canInviteUsers: canInviteUsers,
|
|
||||||
canSendStateEvent: { allowedStateEvents.contains($0) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
static var mockAdmin: RoomMemberProxyMock {
|
static var mockAdmin: RoomMemberProxyMock {
|
||||||
RoomMemberProxyMock(with: .init(userID: "@admin:matrix.org",
|
RoomMemberProxyMock(with: .init(userID: "@admin:matrix.org",
|
||||||
displayName: "Arthur",
|
displayName: "Arthur",
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ struct RoomProxyMockConfiguration {
|
|||||||
|
|
||||||
var members: [RoomMemberProxyMock] = .allMembers
|
var members: [RoomMemberProxyMock] = .allMembers
|
||||||
var memberForID: RoomMemberProxyMock = .mockMe
|
var memberForID: RoomMemberProxyMock = .mockMe
|
||||||
var ownUserID = "@alice:somewhere.org"
|
var ownUserID = RoomMemberProxyMock.mockMe.userID
|
||||||
|
|
||||||
|
var canUserInvite = true
|
||||||
var canUserTriggerRoomNotification = false
|
var canUserTriggerRoomNotification = false
|
||||||
var canUserJoinCall = true
|
var canUserJoinCall = true
|
||||||
}
|
}
|
||||||
@@ -89,7 +90,17 @@ extension RoomProxyMock {
|
|||||||
|
|
||||||
currentPowerLevelChangesReturnValue = .success(.init())
|
currentPowerLevelChangesReturnValue = .success(.init())
|
||||||
applyPowerLevelChangesReturnValue = .success(())
|
applyPowerLevelChangesReturnValue = .success(())
|
||||||
|
canUserUserIDSendStateEventClosure = { [weak self] userID, _ in
|
||||||
|
.success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user)
|
||||||
|
}
|
||||||
|
canUserInviteUserIDReturnValue = .success(configuration.canUserInvite)
|
||||||
canUserRedactOtherUserIDReturnValue = .success(false)
|
canUserRedactOtherUserIDReturnValue = .success(false)
|
||||||
|
canUserKickUserIDClosure = { [weak self] userID in
|
||||||
|
.success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user)
|
||||||
|
}
|
||||||
|
canUserBanUserIDClosure = { [weak self] userID in
|
||||||
|
.success(self?.membersPublisher.value.first { $0.userID == userID }?.role ?? .user != .user)
|
||||||
|
}
|
||||||
canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification)
|
canUserTriggerRoomNotificationUserIDReturnValue = .success(configuration.canUserTriggerRoomNotification)
|
||||||
canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall)
|
canUserJoinCallUserIDReturnValue = .success(configuration.canUserJoinCall)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
|||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
suggestionsPublisher = suggestionTriggerSubject
|
suggestionsPublisher = suggestionTriggerSubject
|
||||||
.combineLatest(roomProxy.membersPublisher)
|
.combineLatest(roomProxy.membersPublisher)
|
||||||
.map { [weak self] suggestionPattern, members -> [SuggestionItem] in
|
.map { [weak self, ownUserID = roomProxy.ownUserID] suggestionPattern, members -> [SuggestionItem] in
|
||||||
guard let self,
|
guard let self,
|
||||||
let suggestionPattern else {
|
let suggestionPattern else {
|
||||||
return []
|
return []
|
||||||
@@ -38,7 +38,7 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
|||||||
case .user:
|
case .user:
|
||||||
var membersSuggestion = members
|
var membersSuggestion = members
|
||||||
.compactMap { member -> SuggestionItem? in
|
.compactMap { member -> SuggestionItem? in
|
||||||
guard !member.isAccountOwner,
|
guard member.userID != ownUserID,
|
||||||
member.membership == .join,
|
member.membership == .join,
|
||||||
Self.isIncluded(searchText: suggestionPattern.text, userID: member.userID, displayName: member.displayName) else {
|
Self.isIncluded(searchText: suggestionPattern.text, userID: member.userID, displayName: member.displayName) else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ struct ReportContentScreenCoordinatorParameters {
|
|||||||
let eventID: String
|
let eventID: String
|
||||||
let senderID: String
|
let senderID: String
|
||||||
let roomProxy: RoomProxyProtocol
|
let roomProxy: RoomProxyProtocol
|
||||||
|
let clientProxy: ClientProxyProtocol
|
||||||
let userIndicatorController: UserIndicatorControllerProtocol
|
let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +43,10 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
|
|||||||
init(parameters: ReportContentScreenCoordinatorParameters) {
|
init(parameters: ReportContentScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
||||||
viewModel = ReportContentScreenViewModel(eventID: parameters.eventID, senderID: parameters.senderID, roomProxy: parameters.roomProxy)
|
viewModel = ReportContentScreenViewModel(eventID: parameters.eventID,
|
||||||
|
senderID: parameters.senderID,
|
||||||
|
roomProxy: parameters.roomProxy,
|
||||||
|
clientProxy: parameters.clientProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
@@ -55,9 +59,9 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
|
|||||||
switch action {
|
switch action {
|
||||||
case .submitStarted:
|
case .submitStarted:
|
||||||
startLoading()
|
startLoading()
|
||||||
case let .submitFailed(error):
|
case let .submitFailed(message):
|
||||||
stopLoading()
|
stopLoading()
|
||||||
showError(description: error.localizedDescription)
|
showError(description: message)
|
||||||
case .submitFinished:
|
case .submitFinished:
|
||||||
stopLoading()
|
stopLoading()
|
||||||
actionsSubject.send(.finish)
|
actionsSubject.send(.finish)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ enum ReportContentScreenViewModelAction: Equatable {
|
|||||||
case cancel
|
case cancel
|
||||||
case submitStarted
|
case submitStarted
|
||||||
case submitFinished
|
case submitFinished
|
||||||
case submitFailed(error: RoomProxyError)
|
case submitFailed(message: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReportContentScreenViewState: BindableState {
|
struct ReportContentScreenViewState: BindableState {
|
||||||
|
|||||||
@@ -23,16 +23,18 @@ class ReportContentScreenViewModel: ReportContentScreenViewModelType, ReportCont
|
|||||||
private let eventID: String
|
private let eventID: String
|
||||||
private let senderID: String
|
private let senderID: String
|
||||||
private let roomProxy: RoomProxyProtocol
|
private let roomProxy: RoomProxyProtocol
|
||||||
|
private let clientProxy: ClientProxyProtocol
|
||||||
private let actionsSubject: PassthroughSubject<ReportContentScreenViewModelAction, Never> = .init()
|
private let actionsSubject: PassthroughSubject<ReportContentScreenViewModelAction, Never> = .init()
|
||||||
|
|
||||||
var actions: AnyPublisher<ReportContentScreenViewModelAction, Never> {
|
var actions: AnyPublisher<ReportContentScreenViewModelAction, Never> {
|
||||||
actionsSubject.eraseToAnyPublisher()
|
actionsSubject.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(eventID: String, senderID: String, roomProxy: RoomProxyProtocol) {
|
init(eventID: String, senderID: String, roomProxy: RoomProxyProtocol, clientProxy: ClientProxyProtocol) {
|
||||||
self.eventID = eventID
|
self.eventID = eventID
|
||||||
self.senderID = senderID
|
self.senderID = senderID
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
|
self.clientProxy = clientProxy
|
||||||
|
|
||||||
super.init(initialViewState: ReportContentScreenViewState(bindings: ReportContentScreenViewStateBindings(reasonText: "", ignoreUser: false)))
|
super.init(initialViewState: ReportContentScreenViewState(bindings: ReportContentScreenViewStateBindings(reasonText: "", ignoreUser: false)))
|
||||||
}
|
}
|
||||||
@@ -55,14 +57,14 @@ class ReportContentScreenViewModel: ReportContentScreenViewModelType, ReportCont
|
|||||||
|
|
||||||
if case let .failure(error) = await roomProxy.reportContent(eventID, reason: state.bindings.reasonText) {
|
if case let .failure(error) = await roomProxy.reportContent(eventID, reason: state.bindings.reasonText) {
|
||||||
MXLog.error("Submit Report Content failed: \(error)")
|
MXLog.error("Submit Report Content failed: \(error)")
|
||||||
actionsSubject.send(.submitFailed(error: error))
|
actionsSubject.send(.submitFailed(message: error.localizedDescription))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore the sender if the user wants to.
|
// Ignore the sender if the user wants to.
|
||||||
if state.bindings.ignoreUser, case let .failure(error) = await roomProxy.ignoreUser(senderID) {
|
if state.bindings.ignoreUser, case let .failure(error) = await clientProxy.ignoreUser(senderID) {
|
||||||
MXLog.error("Ignore user failed: \(error)")
|
MXLog.error("Ignore user failed: \(error)")
|
||||||
actionsSubject.send(.submitFailed(error: error))
|
actionsSubject.send(.submitFailed(message: error.localizedDescription))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ struct ReportContentScreen: View {
|
|||||||
struct ReportContentScreen_Previews: PreviewProvider, TestablePreview {
|
struct ReportContentScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
static let viewModel = ReportContentScreenViewModel(eventID: "",
|
static let viewModel = ReportContentScreenViewModel(eventID: "",
|
||||||
senderID: "",
|
senderID: "",
|
||||||
roomProxy: RoomProxyMock(with: .init()))
|
roomProxy: RoomProxyMock(with: .init()),
|
||||||
|
clientProxy: ClientProxyMock(.init()))
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
|||||||
+2
-4
@@ -18,10 +18,9 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct RoomDetailsEditScreenCoordinatorParameters {
|
struct RoomDetailsEditScreenCoordinatorParameters {
|
||||||
let accountOwner: RoomMemberProxyProtocol
|
let roomProxy: RoomProxyProtocol
|
||||||
let mediaProvider: MediaProviderProtocol
|
let mediaProvider: MediaProviderProtocol
|
||||||
weak var navigationStackCoordinator: NavigationStackCoordinator?
|
weak var navigationStackCoordinator: NavigationStackCoordinator?
|
||||||
let roomProxy: RoomProxyProtocol
|
|
||||||
let userIndicatorController: UserIndicatorControllerProtocol
|
let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
let orientationManager: OrientationManagerProtocol
|
let orientationManager: OrientationManagerProtocol
|
||||||
}
|
}
|
||||||
@@ -43,9 +42,8 @@ final class RoomDetailsEditScreenCoordinator: CoordinatorProtocol {
|
|||||||
init(parameters: RoomDetailsEditScreenCoordinatorParameters) {
|
init(parameters: RoomDetailsEditScreenCoordinatorParameters) {
|
||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
|
|
||||||
viewModel = RoomDetailsEditScreenViewModel(accountOwner: parameters.accountOwner,
|
viewModel = RoomDetailsEditScreenViewModel(roomProxy: parameters.roomProxy,
|
||||||
mediaProvider: parameters.mediaProvider,
|
mediaProvider: parameters.mediaProvider,
|
||||||
roomProxy: parameters.roomProxy,
|
|
||||||
userIndicatorController: parameters.userIndicatorController)
|
userIndicatorController: parameters.userIndicatorController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ struct RoomDetailsEditScreenViewState: BindableState {
|
|||||||
let initialAvatarURL: URL?
|
let initialAvatarURL: URL?
|
||||||
let initialName: String
|
let initialName: String
|
||||||
let initialTopic: String
|
let initialTopic: String
|
||||||
let canEditAvatar: Bool
|
var canEditAvatar = false
|
||||||
let canEditName: Bool
|
var canEditName = false
|
||||||
let canEditTopic: Bool
|
var canEditTopic = false
|
||||||
var avatarURL: URL?
|
var avatarURL: URL?
|
||||||
var localMedia: MediaInfo?
|
var localMedia: MediaInfo?
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,8 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
|||||||
actionsSubject.eraseToAnyPublisher()
|
actionsSubject.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(accountOwner: RoomMemberProxyProtocol,
|
init(roomProxy: RoomProxyProtocol,
|
||||||
mediaProvider: MediaProviderProtocol,
|
mediaProvider: MediaProviderProtocol,
|
||||||
roomProxy: RoomProxyProtocol,
|
|
||||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
self.userIndicatorController = userIndicatorController
|
self.userIndicatorController = userIndicatorController
|
||||||
@@ -44,11 +43,15 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
|||||||
initialAvatarURL: roomAvatar,
|
initialAvatarURL: roomAvatar,
|
||||||
initialName: roomName ?? "",
|
initialName: roomName ?? "",
|
||||||
initialTopic: roomTopic ?? "",
|
initialTopic: roomTopic ?? "",
|
||||||
canEditAvatar: accountOwner.canSendStateEvent(type: .roomAvatar),
|
|
||||||
canEditName: accountOwner.canSendStateEvent(type: .roomName),
|
|
||||||
canEditTopic: accountOwner.canSendStateEvent(type: .roomTopic),
|
|
||||||
avatarURL: roomAvatar,
|
avatarURL: roomAvatar,
|
||||||
bindings: .init(name: roomName ?? "", topic: roomTopic ?? "")), imageProvider: mediaProvider)
|
bindings: .init(name: roomName ?? "", topic: roomTopic ?? "")), imageProvider: mediaProvider)
|
||||||
|
|
||||||
|
Task {
|
||||||
|
// Can't use async let because the mocks aren't thread safe when calling the same method 🤦♂️
|
||||||
|
state.canEditAvatar = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomAvatar) == .success(true)
|
||||||
|
state.canEditName = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomName) == .success(true)
|
||||||
|
state.canEditTopic = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomTopic) == .success(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
|||||||
@@ -156,16 +156,18 @@ struct RoomDetailsEditScreen: View {
|
|||||||
// MARK: - Previews
|
// MARK: - Previews
|
||||||
|
|
||||||
struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
static let viewModel = RoomDetailsEditScreenViewModel(accountOwner: RoomMemberProxyMock.mockAlice,
|
static let viewModel = RoomDetailsEditScreenViewModel(roomProxy: RoomProxyMock(with: .init(id: "test_id",
|
||||||
|
name: "Room",
|
||||||
|
members: [.mockMeAdmin])),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
roomProxy: RoomProxyMock(with: .init(id: "test_id", name: "Room")),
|
|
||||||
userIndicatorController: UserIndicatorControllerMock.default)
|
userIndicatorController: UserIndicatorControllerMock.default)
|
||||||
|
|
||||||
static let readOnlyViewModel = {
|
static let readOnlyViewModel = {
|
||||||
let accountOwner = RoomMemberProxyMock.mockOwner(allowedStateEvents: [])
|
let accountOwner = RoomMemberProxyMock.mockMe
|
||||||
return RoomDetailsEditScreenViewModel(accountOwner: accountOwner,
|
return RoomDetailsEditScreenViewModel(roomProxy: RoomProxyMock(with: .init(id: "test_id",
|
||||||
|
name: "Room",
|
||||||
|
members: [.mockMe])),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
roomProxy: RoomProxyMock(with: .init(id: "test_id", name: "Room")),
|
|
||||||
userIndicatorController: UserIndicatorControllerMock.default)
|
userIndicatorController: UserIndicatorControllerMock.default)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -174,10 +176,12 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
RoomDetailsEditScreen(context: viewModel.context)
|
RoomDetailsEditScreen(context: viewModel.context)
|
||||||
}
|
}
|
||||||
.previewDisplayName("Normal")
|
.previewDisplayName("Normal")
|
||||||
|
.snapshot(delay: 0.1)
|
||||||
|
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
RoomDetailsEditScreen(context: readOnlyViewModel.context)
|
RoomDetailsEditScreen(context: readOnlyViewModel.context)
|
||||||
}
|
}
|
||||||
.previewDisplayName("Read only")
|
.previewDisplayName("Read only")
|
||||||
|
.snapshot(delay: 0.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct RoomDetailsScreenCoordinatorParameters {
|
struct RoomDetailsScreenCoordinatorParameters {
|
||||||
let accountUserID: String
|
|
||||||
let roomProxy: RoomProxyProtocol
|
let roomProxy: RoomProxyProtocol
|
||||||
|
let clientProxy: ClientProxyProtocol
|
||||||
let mediaProvider: MediaProviderProtocol
|
let mediaProvider: MediaProviderProtocol
|
||||||
let analyticsService: AnalyticsService
|
let analyticsService: AnalyticsService
|
||||||
let userIndicatorController: UserIndicatorControllerProtocol
|
let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
@@ -30,7 +30,7 @@ struct RoomDetailsScreenCoordinatorParameters {
|
|||||||
enum RoomDetailsScreenCoordinatorAction {
|
enum RoomDetailsScreenCoordinatorAction {
|
||||||
case leftRoom
|
case leftRoom
|
||||||
case presentRoomMembersList
|
case presentRoomMembersList
|
||||||
case presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol)
|
case presentRoomDetailsEditScreen
|
||||||
case presentNotificationSettingsScreen
|
case presentNotificationSettingsScreen
|
||||||
case presentInviteUsersScreen
|
case presentInviteUsersScreen
|
||||||
case presentPollsHistory
|
case presentPollsHistory
|
||||||
@@ -47,8 +47,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: RoomDetailsScreenCoordinatorParameters) {
|
init(parameters: RoomDetailsScreenCoordinatorParameters) {
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: parameters.accountUserID,
|
viewModel = RoomDetailsScreenViewModel(roomProxy: parameters.roomProxy,
|
||||||
roomProxy: parameters.roomProxy,
|
clientProxy: parameters.clientProxy,
|
||||||
mediaProvider: parameters.mediaProvider,
|
mediaProvider: parameters.mediaProvider,
|
||||||
analyticsService: parameters.analyticsService,
|
analyticsService: parameters.analyticsService,
|
||||||
userIndicatorController: parameters.userIndicatorController,
|
userIndicatorController: parameters.userIndicatorController,
|
||||||
@@ -70,8 +70,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
|||||||
actionsSubject.send(.presentInviteUsersScreen)
|
actionsSubject.send(.presentInviteUsersScreen)
|
||||||
case .leftRoom:
|
case .leftRoom:
|
||||||
actionsSubject.send(.leftRoom)
|
actionsSubject.send(.leftRoom)
|
||||||
case .requestEditDetailsPresentation(let accountOwner):
|
case .requestEditDetailsPresentation:
|
||||||
actionsSubject.send(.presentRoomDetailsEditScreen(accountOwner: accountOwner))
|
actionsSubject.send(.presentRoomDetailsEditScreen)
|
||||||
case .requestNotificationSettingsPresentation:
|
case .requestNotificationSettingsPresentation:
|
||||||
actionsSubject.send(.presentNotificationSettingsScreen)
|
actionsSubject.send(.presentNotificationSettingsScreen)
|
||||||
case .requestPollsHistoryPresentation:
|
case .requestPollsHistoryPresentation:
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ enum RoomDetailsScreenViewModelAction {
|
|||||||
case requestMemberDetailsPresentation
|
case requestMemberDetailsPresentation
|
||||||
case requestInvitePeoplePresentation
|
case requestInvitePeoplePresentation
|
||||||
case leftRoom
|
case leftRoom
|
||||||
case requestEditDetailsPresentation(RoomMemberProxyProtocol)
|
case requestEditDetailsPresentation
|
||||||
case requestPollsHistoryPresentation
|
case requestPollsHistoryPresentation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,18 +20,14 @@ import SwiftUI
|
|||||||
typealias RoomDetailsScreenViewModelType = StateStoreViewModel<RoomDetailsScreenViewState, RoomDetailsScreenViewAction>
|
typealias RoomDetailsScreenViewModelType = StateStoreViewModel<RoomDetailsScreenViewState, RoomDetailsScreenViewAction>
|
||||||
|
|
||||||
class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScreenViewModelProtocol {
|
class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScreenViewModelProtocol {
|
||||||
private let accountUserID: String
|
|
||||||
private let roomProxy: RoomProxyProtocol
|
private let roomProxy: RoomProxyProtocol
|
||||||
|
private let clientProxy: ClientProxyProtocol
|
||||||
private let analyticsService: AnalyticsService
|
private let analyticsService: AnalyticsService
|
||||||
private let mediaProvider: MediaProviderProtocol
|
private let mediaProvider: MediaProviderProtocol
|
||||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
private let notificationSettingsProxy: NotificationSettingsProxyProtocol
|
private let notificationSettingsProxy: NotificationSettingsProxyProtocol
|
||||||
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||||
|
|
||||||
private var accountOwner: RoomMemberProxyProtocol? {
|
|
||||||
didSet { updatePowerLevelPermissions() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private var dmRecipient: RoomMemberProxyProtocol?
|
private var dmRecipient: RoomMemberProxyProtocol?
|
||||||
|
|
||||||
private var actionsSubject: PassthroughSubject<RoomDetailsScreenViewModelAction, Never> = .init()
|
private var actionsSubject: PassthroughSubject<RoomDetailsScreenViewModelAction, Never> = .init()
|
||||||
@@ -40,15 +36,15 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
actionsSubject.eraseToAnyPublisher()
|
actionsSubject.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(accountUserID: String,
|
init(roomProxy: RoomProxyProtocol,
|
||||||
roomProxy: RoomProxyProtocol,
|
clientProxy: ClientProxyProtocol,
|
||||||
mediaProvider: MediaProviderProtocol,
|
mediaProvider: MediaProviderProtocol,
|
||||||
analyticsService: AnalyticsService,
|
analyticsService: AnalyticsService,
|
||||||
userIndicatorController: UserIndicatorControllerProtocol,
|
userIndicatorController: UserIndicatorControllerProtocol,
|
||||||
notificationSettingsProxy: NotificationSettingsProxyProtocol,
|
notificationSettingsProxy: NotificationSettingsProxyProtocol,
|
||||||
attributedStringBuilder: AttributedStringBuilderProtocol) {
|
attributedStringBuilder: AttributedStringBuilderProtocol) {
|
||||||
self.accountUserID = accountUserID
|
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
|
self.clientProxy = clientProxy
|
||||||
self.mediaProvider = mediaProvider
|
self.mediaProvider = mediaProvider
|
||||||
self.analyticsService = analyticsService
|
self.analyticsService = analyticsService
|
||||||
self.userIndicatorController = userIndicatorController
|
self.userIndicatorController = userIndicatorController
|
||||||
@@ -69,9 +65,10 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
imageProvider: mediaProvider)
|
imageProvider: mediaProvider)
|
||||||
|
|
||||||
updateRoomInfo()
|
updateRoomInfo()
|
||||||
|
Task { await updatePowerLevelPermissions() }
|
||||||
|
|
||||||
setupRoomSubscription()
|
setupRoomSubscription()
|
||||||
fetchMembers()
|
Task { await fetchMembersIfNeeded() }
|
||||||
|
|
||||||
setupNotificationSettingsSubscription()
|
setupNotificationSettingsSubscription()
|
||||||
fetchNotificationSettings()
|
fetchNotificationSettings()
|
||||||
@@ -103,11 +100,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
case .processTapUnignore:
|
case .processTapUnignore:
|
||||||
state.bindings.ignoreUserRoomAlertItem = .init(action: .unignore)
|
state.bindings.ignoreUserRoomAlertItem = .init(action: .unignore)
|
||||||
case .processTapEdit, .processTapAddTopic:
|
case .processTapEdit, .processTapAddTopic:
|
||||||
guard let accountOwner else {
|
actionsSubject.send(.requestEditDetailsPresentation)
|
||||||
MXLog.error("Missing account owner when presenting the room's edit details screen")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
actionsSubject.send(.requestEditDetailsPresentation(accountOwner))
|
|
||||||
case .ignoreConfirmed:
|
case .ignoreConfirmed:
|
||||||
Task { await ignore() }
|
Task { await ignore() }
|
||||||
case .unignoreConfirmed:
|
case .unignoreConfirmed:
|
||||||
@@ -154,13 +147,6 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchMembers() {
|
|
||||||
Task {
|
|
||||||
await fetchMembersIfNeeded()
|
|
||||||
await fetchAccountOwner()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func fetchMembersIfNeeded() async {
|
private func fetchMembersIfNeeded() async {
|
||||||
// We need to fetch members just in 1-to-1 chat to get the member object for the other person
|
// We need to fetch members just in 1-to-1 chat to get the member object for the other person
|
||||||
guard roomProxy.isEncryptedOneToOneRoom else {
|
guard roomProxy.isEncryptedOneToOneRoom else {
|
||||||
@@ -169,9 +155,9 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
|
|
||||||
roomProxy.membersPublisher
|
roomProxy.membersPublisher
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] members in
|
.sink { [weak self, ownUserID = roomProxy.ownUserID] members in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
let dmRecipient = members.first(where: { !$0.isAccountOwner })
|
let dmRecipient = members.first(where: { $0.userID != ownUserID })
|
||||||
self.dmRecipient = dmRecipient
|
self.dmRecipient = dmRecipient
|
||||||
self.state.dmRecipient = dmRecipient.map(RoomMemberDetails.init(withProxy:))
|
self.state.dmRecipient = dmRecipient.map(RoomMemberDetails.init(withProxy:))
|
||||||
}
|
}
|
||||||
@@ -180,20 +166,13 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
await roomProxy.updateMembers()
|
await roomProxy.updateMembers()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchAccountOwner() async {
|
private func updatePowerLevelPermissions() async {
|
||||||
switch await roomProxy.getMember(userID: accountUserID) {
|
async let canInviteUsers = roomProxy.canUserInvite(userID: roomProxy.ownUserID) == .success(true)
|
||||||
case .success(let member):
|
// Can't use async let because the mocks aren't thread safe when calling the same method 🤦♂️
|
||||||
accountOwner = member
|
state.canEditRoomName = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomName) == .success(true)
|
||||||
case .failure(let error):
|
state.canEditRoomTopic = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomTopic) == .success(true)
|
||||||
MXLog.error("Failed (error: \(error) to get account owner member with id: \(accountUserID), in room: \(roomProxy.id)")
|
state.canEditRoomAvatar = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomAvatar) == .success(true)
|
||||||
}
|
state.canInviteUsers = await canInviteUsers
|
||||||
}
|
|
||||||
|
|
||||||
private func updatePowerLevelPermissions() {
|
|
||||||
state.canInviteUsers = accountOwner?.canInviteUsers ?? false
|
|
||||||
state.canEditRoomName = accountOwner?.canSendStateEvent(type: .roomName) ?? false
|
|
||||||
state.canEditRoomTopic = accountOwner?.canSendStateEvent(type: .roomTopic) ?? false
|
|
||||||
state.canEditRoomAvatar = accountOwner?.canSendStateEvent(type: .roomAvatar) ?? false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupNotificationSettingsSubscription() {
|
private func setupNotificationSettingsSubscription() {
|
||||||
@@ -280,8 +259,14 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func ignore() async {
|
private func ignore() async {
|
||||||
|
guard let dmUserID = dmRecipient?.userID else {
|
||||||
|
MXLog.error("Attempting to ignore a nil DM Recipient")
|
||||||
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
state.isProcessingIgnoreRequest = true
|
state.isProcessingIgnoreRequest = true
|
||||||
let result = await dmRecipient?.ignoreUser()
|
let result = await clientProxy.ignoreUser(dmUserID)
|
||||||
state.isProcessingIgnoreRequest = false
|
state.isProcessingIgnoreRequest = false
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
@@ -289,14 +274,20 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
var dmRecipient = state.dmRecipient
|
var dmRecipient = state.dmRecipient
|
||||||
dmRecipient?.isIgnored = true
|
dmRecipient?.isIgnored = true
|
||||||
state.dmRecipient = dmRecipient
|
state.dmRecipient = dmRecipient
|
||||||
case .failure, .none:
|
case .failure:
|
||||||
state.bindings.alertInfo = .init(id: .unknown)
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func unignore() async {
|
private func unignore() async {
|
||||||
|
guard let dmUserID = dmRecipient?.userID else {
|
||||||
|
MXLog.error("Attempting to unignore a nil DM Recipient")
|
||||||
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
state.isProcessingIgnoreRequest = true
|
state.isProcessingIgnoreRequest = true
|
||||||
let result = await dmRecipient?.unignoreUser()
|
let result = await clientProxy.unignoreUser(dmUserID)
|
||||||
state.isProcessingIgnoreRequest = false
|
state.isProcessingIgnoreRequest = false
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
@@ -304,7 +295,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
|||||||
var dmRecipient = state.dmRecipient
|
var dmRecipient = state.dmRecipient
|
||||||
dmRecipient?.isIgnored = false
|
dmRecipient?.isIgnored = false
|
||||||
state.dmRecipient = dmRecipient
|
state.dmRecipient = dmRecipient
|
||||||
case .failure, .none:
|
case .failure:
|
||||||
state.bindings.alertInfo = .init(id: .unknown)
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ struct RoomDetailsScreen: View {
|
|||||||
struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||||
static let genericRoomViewModel = {
|
static let genericRoomViewModel = {
|
||||||
let members: [RoomMemberProxyMock] = [
|
let members: [RoomMemberProxyMock] = [
|
||||||
.mockMe,
|
.mockMeAdmin,
|
||||||
.mockAlice,
|
.mockAlice,
|
||||||
.mockBob,
|
.mockBob,
|
||||||
.mockCharlie
|
.mockCharlie
|
||||||
@@ -304,8 +304,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: notificationSettingsProxyMockConfiguration)
|
let notificationSettingsProxy = NotificationSettingsProxyMock(with: notificationSettingsProxyMockConfiguration)
|
||||||
let appSettings = AppSettings()
|
let appSettings = AppSettings()
|
||||||
|
|
||||||
return RoomDetailsScreenViewModel(accountUserID: RoomMemberProxyMock.mockMe.userID,
|
return RoomDetailsScreenViewModel(roomProxy: roomProxy,
|
||||||
roomProxy: roomProxy,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -330,8 +330,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||||
let appSettings = AppSettings()
|
let appSettings = AppSettings()
|
||||||
|
|
||||||
return RoomDetailsScreenViewModel(accountUserID: RoomMemberProxyMock.mockMe.userID,
|
return RoomDetailsScreenViewModel(roomProxy: roomProxy,
|
||||||
roomProxy: roomProxy,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -342,7 +342,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
|
|
||||||
static let simpleRoomViewModel = {
|
static let simpleRoomViewModel = {
|
||||||
let members: [RoomMemberProxyMock] = [
|
let members: [RoomMemberProxyMock] = [
|
||||||
.mockMe,
|
.mockMeAdmin,
|
||||||
.mockAlice,
|
.mockAlice,
|
||||||
.mockBob,
|
.mockBob,
|
||||||
.mockCharlie
|
.mockCharlie
|
||||||
@@ -355,8 +355,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||||
let appSettings = AppSettings()
|
let appSettings = AppSettings()
|
||||||
|
|
||||||
return RoomDetailsScreenViewModel(accountUserID: RoomMemberProxyMock.mockMe.userID,
|
return RoomDetailsScreenViewModel(roomProxy: roomProxy,
|
||||||
roomProxy: roomProxy,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
|||||||
+5
-3
@@ -18,8 +18,9 @@ import Combine
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct RoomMemberDetailsScreenCoordinatorParameters {
|
struct RoomMemberDetailsScreenCoordinatorParameters {
|
||||||
let roomProxy: RoomProxyProtocol
|
|
||||||
let userID: String
|
let userID: String
|
||||||
|
let roomProxy: RoomProxyProtocol
|
||||||
|
let clientProxy: ClientProxyProtocol
|
||||||
let mediaProvider: MediaProviderProtocol
|
let mediaProvider: MediaProviderProtocol
|
||||||
let userIndicatorController: UserIndicatorControllerProtocol
|
let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
}
|
}
|
||||||
@@ -39,8 +40,9 @@ final class RoomMemberDetailsScreenCoordinator: CoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: RoomMemberDetailsScreenCoordinatorParameters) {
|
init(parameters: RoomMemberDetailsScreenCoordinatorParameters) {
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: parameters.roomProxy,
|
viewModel = RoomMemberDetailsScreenViewModel(userID: parameters.userID,
|
||||||
userID: parameters.userID,
|
roomProxy: parameters.roomProxy,
|
||||||
|
clientProxy: parameters.clientProxy,
|
||||||
mediaProvider: parameters.mediaProvider,
|
mediaProvider: parameters.mediaProvider,
|
||||||
userIndicatorController: parameters.userIndicatorController)
|
userIndicatorController: parameters.userIndicatorController)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ enum RoomMemberDetailsScreenViewModelAction {
|
|||||||
struct RoomMemberDetailsScreenViewState: BindableState {
|
struct RoomMemberDetailsScreenViewState: BindableState {
|
||||||
let userID: String
|
let userID: String
|
||||||
var memberDetails: RoomMemberDetails?
|
var memberDetails: RoomMemberDetails?
|
||||||
|
var isOwnMemberDetails = false
|
||||||
var isProcessingIgnoreRequest = false
|
var isProcessingIgnoreRequest = false
|
||||||
|
|
||||||
var bindings: RoomMemberDetailsScreenViewStateBindings
|
var bindings: RoomMemberDetailsScreenViewStateBindings
|
||||||
|
|||||||
+8
-4
@@ -21,6 +21,7 @@ typealias RoomMemberDetailsScreenViewModelType = StateStoreViewModel<RoomMemberD
|
|||||||
|
|
||||||
class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, RoomMemberDetailsScreenViewModelProtocol {
|
class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, RoomMemberDetailsScreenViewModelProtocol {
|
||||||
private let roomProxy: RoomProxyProtocol
|
private let roomProxy: RoomProxyProtocol
|
||||||
|
private let clientProxy: ClientProxyProtocol
|
||||||
private let mediaProvider: MediaProviderProtocol
|
private let mediaProvider: MediaProviderProtocol
|
||||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||||
|
|
||||||
@@ -32,11 +33,13 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
|||||||
actionsSubject.eraseToAnyPublisher()
|
actionsSubject.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
init(roomProxy: RoomProxyProtocol,
|
init(userID: String,
|
||||||
userID: String,
|
roomProxy: RoomProxyProtocol,
|
||||||
|
clientProxy: ClientProxyProtocol,
|
||||||
mediaProvider: MediaProviderProtocol,
|
mediaProvider: MediaProviderProtocol,
|
||||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
|
self.clientProxy = clientProxy
|
||||||
self.mediaProvider = mediaProvider
|
self.mediaProvider = mediaProvider
|
||||||
self.userIndicatorController = userIndicatorController
|
self.userIndicatorController = userIndicatorController
|
||||||
|
|
||||||
@@ -54,6 +57,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
|||||||
case .success(let member):
|
case .success(let member):
|
||||||
roomMemberProxy = member
|
roomMemberProxy = member
|
||||||
state.memberDetails = RoomMemberDetails(withProxy: member)
|
state.memberDetails = RoomMemberDetails(withProxy: member)
|
||||||
|
state.isOwnMemberDetails = member.userID == roomProxy.ownUserID
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
state.bindings.alertInfo = .init(id: .unknown)
|
state.bindings.alertInfo = .init(id: .unknown)
|
||||||
MXLog.error("[RoomFlowCoordinator] Failed to get member: \(error)")
|
MXLog.error("[RoomFlowCoordinator] Failed to get member: \(error)")
|
||||||
@@ -100,7 +104,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.isProcessingIgnoreRequest = true
|
state.isProcessingIgnoreRequest = true
|
||||||
let result = await roomMemberProxy.ignoreUser()
|
let result = await clientProxy.ignoreUser(roomMemberProxy.userID)
|
||||||
state.isProcessingIgnoreRequest = false
|
state.isProcessingIgnoreRequest = false
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
@@ -118,7 +122,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
state.isProcessingIgnoreRequest = true
|
state.isProcessingIgnoreRequest = true
|
||||||
let result = await roomMemberProxy.unignoreUser()
|
let result = await clientProxy.unignoreUser(roomMemberProxy.userID)
|
||||||
state.isProcessingIgnoreRequest = false
|
state.isProcessingIgnoreRequest = false
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
|
|||||||
+10
-8
@@ -36,8 +36,7 @@ struct RoomMemberDetailsScreen: View {
|
|||||||
Form {
|
Form {
|
||||||
headerSection
|
headerSection
|
||||||
|
|
||||||
if let memberDetails = context.viewState.memberDetails,
|
if context.viewState.memberDetails != nil, !context.viewState.isOwnMemberDetails {
|
||||||
!memberDetails.isAccountOwner {
|
|
||||||
directChatSection
|
directChatSection
|
||||||
blockUserSection
|
blockUserSection
|
||||||
}
|
}
|
||||||
@@ -124,8 +123,9 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||||
|
|
||||||
return RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||||
userID: member.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}()
|
}()
|
||||||
@@ -135,8 +135,9 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||||
|
|
||||||
return RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||||
userID: member.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}()
|
}()
|
||||||
@@ -146,8 +147,9 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||||
|
|
||||||
return RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||||
userID: member.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -106,11 +106,14 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
|||||||
invitedMembers: roomMembersDetails.invitedMembers,
|
invitedMembers: roomMembersDetails.invitedMembers,
|
||||||
bannedMembers: roomMembersDetails.bannedMembers,
|
bannedMembers: roomMembersDetails.bannedMembers,
|
||||||
bindings: state.bindings)
|
bindings: state.bindings)
|
||||||
if let accountOwner = roomMembersDetails.accountOwner {
|
|
||||||
self.state.canInviteUsers = accountOwner.canInviteUsers
|
async let canInviteUsers = roomProxy.canUserInvite(userID: roomProxy.ownUserID)
|
||||||
self.state.canKickUsers = accountOwner.canKickUsers
|
async let canKickUsers = roomProxy.canUserKick(userID: roomProxy.ownUserID)
|
||||||
self.state.canBanUsers = accountOwner.canBanUsers
|
async let canBanUsers = roomProxy.canUserBan(userID: roomProxy.ownUserID)
|
||||||
}
|
self.state.canInviteUsers = await canInviteUsers == .success(true)
|
||||||
|
self.state.canKickUsers = await canKickUsers == .success(true)
|
||||||
|
self.state.canBanUsers = await canBanUsers == .success(true)
|
||||||
|
|
||||||
if state.bindings.mode == .banned, roomMembersDetails.bannedMembers.isEmpty {
|
if state.bindings.mode == .banned, roomMembersDetails.bannedMembers.isEmpty {
|
||||||
state.bindings.mode = .members
|
state.bindings.mode = .members
|
||||||
}
|
}
|
||||||
@@ -125,13 +128,8 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
|||||||
var invitedMembers: [RoomMemberDetails] = .init()
|
var invitedMembers: [RoomMemberDetails] = .init()
|
||||||
var joinedMembers: [RoomMemberDetails] = .init()
|
var joinedMembers: [RoomMemberDetails] = .init()
|
||||||
var bannedMembers: [RoomMemberDetails] = .init()
|
var bannedMembers: [RoomMemberDetails] = .init()
|
||||||
var accountOwner: RoomMemberProxyProtocol?
|
|
||||||
|
|
||||||
for member in members {
|
for member in members {
|
||||||
if accountOwner == nil, member.isAccountOwner {
|
|
||||||
accountOwner = member
|
|
||||||
}
|
|
||||||
|
|
||||||
switch member.membership {
|
switch member.membership {
|
||||||
case .invite:
|
case .invite:
|
||||||
invitedMembers.append(.init(withProxy: member))
|
invitedMembers.append(.init(withProxy: member))
|
||||||
@@ -146,8 +144,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
|||||||
|
|
||||||
return .init(invitedMembers: invitedMembers,
|
return .init(invitedMembers: invitedMembers,
|
||||||
joinedMembers: joinedMembers,
|
joinedMembers: joinedMembers,
|
||||||
bannedMembers: bannedMembers.sorted { $0.id.localizedStandardCompare($1.id) == .orderedAscending }, // Re-sort ignoring display name.
|
bannedMembers: bannedMembers.sorted { $0.id.localizedStandardCompare($1.id) == .orderedAscending }) // Re-sort ignoring display name.
|
||||||
accountOwner: accountOwner)
|
|
||||||
}
|
}
|
||||||
.value
|
.value
|
||||||
}
|
}
|
||||||
@@ -257,5 +254,4 @@ private struct RoomMembersDetails {
|
|||||||
var invitedMembers: [RoomMemberDetails]
|
var invitedMembers: [RoomMemberDetails]
|
||||||
var joinedMembers: [RoomMemberDetails]
|
var joinedMembers: [RoomMemberDetails]
|
||||||
var bannedMembers: [RoomMemberDetails]
|
var bannedMembers: [RoomMemberDetails]
|
||||||
var accountOwner: RoomMemberProxyProtocol?
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,10 +142,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
initialMode: RoomMembersListScreenMode = .members) -> RoomMembersListScreenViewModel {
|
initialMode: RoomMembersListScreenMode = .members) -> RoomMembersListScreenViewModel {
|
||||||
let mockAdmin = RoomMemberProxyMock.mockAdmin
|
let mockAdmin = RoomMemberProxyMock.mockAdmin
|
||||||
|
|
||||||
if isAdmin {
|
let ownUserID = isAdmin ? mockAdmin.userID : RoomMemberProxyMock.mockMe.userID
|
||||||
mockAdmin.underlyingCanBanUsers = true
|
|
||||||
mockAdmin.underlyingIsAccountOwner = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var members: [RoomMemberProxyMock] = [
|
var members: [RoomMemberProxyMock] = [
|
||||||
.mockAlice,
|
.mockAlice,
|
||||||
@@ -160,7 +157,10 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return RoomMembersListScreenViewModel(initialMode: initialMode,
|
return RoomMembersListScreenViewModel(initialMode: initialMode,
|
||||||
roomProxy: RoomProxyMock(with: .init(name: "Some room", members: members)),
|
roomProxy: RoomProxyMock(with: .init(name: "Some room",
|
||||||
|
members: members,
|
||||||
|
ownUserID: ownUserID,
|
||||||
|
canUserInvite: false)),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
appSettings: ServiceLocator.shared.settings)
|
appSettings: ServiceLocator.shared.settings)
|
||||||
|
|||||||
@@ -589,7 +589,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
|||||||
guard
|
guard
|
||||||
let members = await roomProxy.members(),
|
let members = await roomProxy.members(),
|
||||||
members.count == 2,
|
members.count == 2,
|
||||||
let otherPerson = members.first(where: { !$0.isAccountOwner && $0.membership == .leave })
|
let otherPerson = members.first(where: { $0.userID != roomProxy.ownUserID && $0.membership == .leave })
|
||||||
else {
|
else {
|
||||||
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ struct RoomMemberDetails: Identifiable, Hashable {
|
|||||||
let name: String?
|
let name: String?
|
||||||
let avatarURL: URL?
|
let avatarURL: URL?
|
||||||
let permalink: URL?
|
let permalink: URL?
|
||||||
let isAccountOwner: Bool
|
|
||||||
var isIgnored: Bool
|
var isIgnored: Bool
|
||||||
var isBanned: Bool
|
var isBanned: Bool
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ extension RoomMemberDetails {
|
|||||||
name = proxy.displayName
|
name = proxy.displayName
|
||||||
avatarURL = proxy.avatarURL
|
avatarURL = proxy.avatarURL
|
||||||
permalink = proxy.permalink
|
permalink = proxy.permalink
|
||||||
isAccountOwner = proxy.isAccountOwner
|
|
||||||
isIgnored = proxy.isIgnored
|
isIgnored = proxy.isIgnored
|
||||||
isBanned = proxy.membership == .ban
|
isBanned = proxy.membership == .ban
|
||||||
role = .init(proxy.role)
|
role = .init(proxy.role)
|
||||||
@@ -47,7 +47,7 @@ extension RoomMemberDetails {
|
|||||||
name = nil
|
name = nil
|
||||||
avatarURL = nil
|
avatarURL = nil
|
||||||
permalink = nil
|
permalink = nil
|
||||||
isAccountOwner = false
|
|
||||||
isIgnored = false
|
isIgnored = false
|
||||||
isBanned = false
|
isBanned = false
|
||||||
role = .user
|
role = .user
|
||||||
|
|||||||
@@ -19,69 +19,25 @@ import MatrixRustSDK
|
|||||||
|
|
||||||
final class RoomMemberProxy: RoomMemberProxyProtocol {
|
final class RoomMemberProxy: RoomMemberProxyProtocol {
|
||||||
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
||||||
private let member: RoomMemberProtocol
|
private let member: RoomMember
|
||||||
|
|
||||||
private let backgroundAccountDataTaskName = "SendAccountDataEvent"
|
private let backgroundAccountDataTaskName = "SendAccountDataEvent"
|
||||||
private var sendAccountDataEventBackgroundTask: BackgroundTaskProtocol?
|
private var sendAccountDataEventBackgroundTask: BackgroundTaskProtocol?
|
||||||
|
|
||||||
private let userInitiatedDispatchQueue = DispatchQueue(label: "io.element.elementx.roommemberproxy.userinitiated", qos: .userInitiated)
|
private let userInitiatedDispatchQueue = DispatchQueue(label: "io.element.elementx.roommemberproxy.userinitiated", qos: .userInitiated)
|
||||||
|
|
||||||
init(member: RoomMemberProtocol, backgroundTaskService: BackgroundTaskServiceProtocol) {
|
init(member: RoomMember, backgroundTaskService: BackgroundTaskServiceProtocol) {
|
||||||
self.backgroundTaskService = backgroundTaskService
|
self.backgroundTaskService = backgroundTaskService
|
||||||
self.member = member
|
self.member = member
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy var userID = member.userId()
|
var userID: String { member.userId }
|
||||||
|
var displayName: String? { member.displayName }
|
||||||
|
var avatarURL: URL? { member.avatarUrl.flatMap(URL.init(string:)) }
|
||||||
|
|
||||||
lazy var displayName = member.displayName()
|
var membership: MembershipState { member.membership }
|
||||||
|
var isIgnored: Bool { member.isIgnored }
|
||||||
|
|
||||||
lazy var avatarURL = member.avatarUrl().flatMap(URL.init(string:))
|
var powerLevel: Int { Int(member.powerLevel) }
|
||||||
|
var role: RoomMemberRole { member.suggestedRoleForPowerLevel }
|
||||||
lazy var membership = member.membership()
|
|
||||||
|
|
||||||
lazy var isAccountOwner = member.isAccountUser()
|
|
||||||
|
|
||||||
lazy var isIgnored = member.isIgnored()
|
|
||||||
|
|
||||||
lazy var powerLevel = Int(member.powerLevel())
|
|
||||||
lazy var role = member.suggestedRoleForPowerLevel()
|
|
||||||
lazy var canInviteUsers = member.canInvite()
|
|
||||||
lazy var canKickUsers = member.canKick()
|
|
||||||
lazy var canBanUsers = member.canBan()
|
|
||||||
|
|
||||||
func canSendStateEvent(type: StateEventType) -> Bool {
|
|
||||||
member.canSendState(stateEvent: type)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ignoreUser() async -> Result<Void, RoomMemberProxyError> {
|
|
||||||
sendAccountDataEventBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundAccountDataTaskName, isReusable: true)
|
|
||||||
defer {
|
|
||||||
sendAccountDataEventBackgroundTask?.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Task.dispatch(on: userInitiatedDispatchQueue) {
|
|
||||||
do {
|
|
||||||
try self.member.ignore()
|
|
||||||
return .success(())
|
|
||||||
} catch {
|
|
||||||
return .failure(.ignoreUserFailed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func unignoreUser() async -> Result<Void, RoomMemberProxyError> {
|
|
||||||
sendAccountDataEventBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundAccountDataTaskName, isReusable: true)
|
|
||||||
defer {
|
|
||||||
sendAccountDataEventBackgroundTask?.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
return await Task.dispatch(on: userInitiatedDispatchQueue) {
|
|
||||||
do {
|
|
||||||
try self.member.unignore()
|
|
||||||
return .success(())
|
|
||||||
} catch {
|
|
||||||
return .failure(.unignoreUserFailed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,19 +27,12 @@ protocol RoomMemberProxyProtocol: AnyObject {
|
|||||||
var userID: String { get }
|
var userID: String { get }
|
||||||
var displayName: String? { get }
|
var displayName: String? { get }
|
||||||
var avatarURL: URL? { get }
|
var avatarURL: URL? { get }
|
||||||
|
|
||||||
var membership: MembershipState { get }
|
var membership: MembershipState { get }
|
||||||
var isAccountOwner: Bool { get }
|
|
||||||
var isIgnored: Bool { get }
|
var isIgnored: Bool { get }
|
||||||
|
|
||||||
var powerLevel: Int { get }
|
var powerLevel: Int { get }
|
||||||
var role: RoomMemberRole { get }
|
var role: RoomMemberRole { get }
|
||||||
var canInviteUsers: Bool { get }
|
|
||||||
var canKickUsers: Bool { get }
|
|
||||||
var canBanUsers: Bool { get }
|
|
||||||
|
|
||||||
func ignoreUser() async -> Result<Void, RoomMemberProxyError>
|
|
||||||
func unignoreUser() async -> Result<Void, RoomMemberProxyError>
|
|
||||||
func canSendStateEvent(type: StateEventType) -> Bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension RoomMemberProxyProtocol {
|
extension RoomMemberProxyProtocol {
|
||||||
|
|||||||
@@ -234,20 +234,6 @@ class RoomProxy: RoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ignoreUser(_ userID: String) async -> Result<Void, RoomProxyError> {
|
|
||||||
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
|
||||||
defer {
|
|
||||||
sendMessageBackgroundTask?.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
try await room.ignoreUser(userId: userID)
|
|
||||||
return .success(())
|
|
||||||
} catch {
|
|
||||||
return .failure(.failedIgnoringUser)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func leaveRoom() async -> Result<Void, RoomProxyError> {
|
func leaveRoom() async -> Result<Void, RoomProxyError> {
|
||||||
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
sendMessageBackgroundTask = await backgroundTaskService.startBackgroundTask(withName: backgroundTaskName, isReusable: true)
|
||||||
defer {
|
defer {
|
||||||
@@ -409,6 +395,24 @@ class RoomProxy: RoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result<Bool, RoomProxyError> {
|
||||||
|
do {
|
||||||
|
return try await .success(room.canUserSendState(userId: userID, stateEvent: event))
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed checking if the user can send \(event) with error: \(error)")
|
||||||
|
return .failure(.failedCheckingPermission)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func canUserInvite(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
|
do {
|
||||||
|
return try await .success(room.canUserInvite(userId: userID))
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed checking if the user can invite with error: \(error)")
|
||||||
|
return .failure(.failedCheckingPermission)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func canUserRedactOther(userID: String) async -> Result<Bool, RoomProxyError> {
|
func canUserRedactOther(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
return try await .success(room.canUserRedactOther(userId: userID))
|
return try await .success(room.canUserRedactOther(userId: userID))
|
||||||
@@ -427,6 +431,24 @@ class RoomProxy: RoomProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canUserKick(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
|
do {
|
||||||
|
return try await .success(room.canUserKick(userId: userID))
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed checking if the user can kick with error: \(error)")
|
||||||
|
return .failure(.failedCheckingPermission)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func canUserBan(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
|
do {
|
||||||
|
return try await .success(room.canUserBan(userId: userID))
|
||||||
|
} catch {
|
||||||
|
MXLog.error("Failed checking if the user can ban with error: \(error)")
|
||||||
|
return .failure(.failedCheckingPermission)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError> {
|
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError> {
|
||||||
do {
|
do {
|
||||||
return try await .success(room.canUserTriggerRoomNotification(userId: userID))
|
return try await .success(room.canUserTriggerRoomNotification(userId: userID))
|
||||||
|
|||||||
@@ -83,8 +83,6 @@ protocol RoomProxyProtocol {
|
|||||||
|
|
||||||
func reportContent(_ eventID: String, reason: String?) async -> Result<Void, RoomProxyError>
|
func reportContent(_ eventID: String, reason: String?) async -> Result<Void, RoomProxyError>
|
||||||
|
|
||||||
func ignoreUser(_ userID: String) async -> Result<Void, RoomProxyError>
|
|
||||||
|
|
||||||
func leaveRoom() async -> Result<Void, RoomProxyError>
|
func leaveRoom() async -> Result<Void, RoomProxyError>
|
||||||
|
|
||||||
func updateMembers() async
|
func updateMembers() async
|
||||||
@@ -120,8 +118,12 @@ protocol RoomProxyProtocol {
|
|||||||
|
|
||||||
func currentPowerLevelChanges() async -> Result<RoomPowerLevelChanges, RoomProxyError>
|
func currentPowerLevelChanges() async -> Result<RoomPowerLevelChanges, RoomProxyError>
|
||||||
func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result<Void, RoomProxyError>
|
func applyPowerLevelChanges(_ changes: RoomPowerLevelChanges) async -> Result<Void, RoomProxyError>
|
||||||
|
func canUser(userID: String, sendStateEvent event: StateEventType) async -> Result<Bool, RoomProxyError>
|
||||||
|
func canUserInvite(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
func canUserRedactOther(userID: String) async -> Result<Bool, RoomProxyError>
|
func canUserRedactOther(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
func canUserRedactOwn(userID: String) async -> Result<Bool, RoomProxyError>
|
func canUserRedactOwn(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
|
func canUserKick(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
|
func canUserBan(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError>
|
func canUserTriggerRoomNotification(userID: String) async -> Result<Bool, RoomProxyError>
|
||||||
|
|
||||||
// MARK: - Moderation
|
// MARK: - Moderation
|
||||||
|
|||||||
@@ -586,9 +586,10 @@ class MockScreen: Identifiable {
|
|||||||
name: "Room",
|
name: "Room",
|
||||||
isEncrypted: true,
|
isEncrypted: true,
|
||||||
members: members,
|
members: members,
|
||||||
memberForID: .mockOwner(allowedStateEvents: [], canInviteUsers: false)))
|
memberForID: .mockMe,
|
||||||
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(accountUserID: "@owner:somewhere.com",
|
canUserInvite: false))
|
||||||
roomProxy: roomProxy,
|
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -607,9 +608,10 @@ class MockScreen: Identifiable {
|
|||||||
isEncrypted: true,
|
isEncrypted: true,
|
||||||
canonicalAlias: "#mock:room.org",
|
canonicalAlias: "#mock:room.org",
|
||||||
members: members,
|
members: members,
|
||||||
memberForID: .mockOwner(allowedStateEvents: [], canInviteUsers: false)))
|
memberForID: .mockMe,
|
||||||
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(accountUserID: "@owner:somewhere.com",
|
canUserInvite: false))
|
||||||
roomProxy: roomProxy,
|
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -620,8 +622,7 @@ class MockScreen: Identifiable {
|
|||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
case .roomDetailsScreenWithEmptyTopic:
|
case .roomDetailsScreenWithEmptyTopic:
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let owner: RoomMemberProxyMock = .mockOwner(allowedStateEvents: [.roomTopic], canInviteUsers: false)
|
let members: [RoomMemberProxyMock] = [.mockMeAdmin, .mockBob, .mockCharlie]
|
||||||
let members: [RoomMemberProxyMock] = [owner, .mockBob, .mockCharlie]
|
|
||||||
let roomProxy = RoomProxyMock(with: .init(id: "MockRoomIdentifier",
|
let roomProxy = RoomProxyMock(with: .init(id: "MockRoomIdentifier",
|
||||||
name: "Room",
|
name: "Room",
|
||||||
topic: nil,
|
topic: nil,
|
||||||
@@ -630,9 +631,10 @@ class MockScreen: Identifiable {
|
|||||||
isEncrypted: true,
|
isEncrypted: true,
|
||||||
canonicalAlias: "#mock:room.org",
|
canonicalAlias: "#mock:room.org",
|
||||||
members: members,
|
members: members,
|
||||||
memberForID: owner))
|
memberForID: .mockMeAdmin,
|
||||||
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(accountUserID: "@owner:somewhere.com",
|
canUserInvite: false))
|
||||||
roomProxy: roomProxy,
|
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -643,15 +645,16 @@ class MockScreen: Identifiable {
|
|||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
case .roomDetailsScreenWithInvite:
|
case .roomDetailsScreenWithInvite:
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let owner: RoomMemberProxyMock = .mockOwner(allowedStateEvents: [], canInviteUsers: true)
|
let owner: RoomMemberProxyMock = .mockMe
|
||||||
let members: [RoomMemberProxyMock] = [owner, .mockBob, .mockCharlie]
|
let members: [RoomMemberProxyMock] = [owner, .mockBob, .mockCharlie]
|
||||||
let roomProxy = RoomProxyMock(with: .init(id: "MockRoomIdentifier",
|
let roomProxy = RoomProxyMock(with: .init(id: "MockRoomIdentifier",
|
||||||
name: "Room",
|
name: "Room",
|
||||||
isEncrypted: true,
|
isEncrypted: true,
|
||||||
members: members,
|
members: members,
|
||||||
memberForID: owner))
|
memberForID: owner,
|
||||||
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(accountUserID: "@owner:somewhere.com",
|
canUserInvite: true))
|
||||||
roomProxy: roomProxy,
|
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -669,9 +672,10 @@ class MockScreen: Identifiable {
|
|||||||
isDirect: true,
|
isDirect: true,
|
||||||
isEncrypted: true,
|
isEncrypted: true,
|
||||||
members: members,
|
members: members,
|
||||||
memberForID: .mockOwner(allowedStateEvents: [], canInviteUsers: false)))
|
memberForID: .mockMe,
|
||||||
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(accountUserID: "@owner:somewhere.com",
|
canUserInvite: false))
|
||||||
roomProxy: roomProxy,
|
let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -681,16 +685,16 @@ class MockScreen: Identifiable {
|
|||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
case .roomEditDetails, .roomEditDetailsReadOnly:
|
case .roomEditDetails, .roomEditDetailsReadOnly:
|
||||||
let allowedStateEvents: [StateEventType] = id == .roomEditDetails ? [.roomAvatar, .roomName, .roomTopic] : []
|
let members: [RoomMemberProxyMock] = id == .roomEditDetails ? [.mockMeAdmin] : [.mockMe]
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let roomProxy = RoomProxyMock(with: .init(id: "MockRoomIdentifier",
|
let roomProxy = RoomProxyMock(with: .init(id: "MockRoomIdentifier",
|
||||||
name: "Room",
|
name: "Room",
|
||||||
topic: "What a cool topic!",
|
topic: "What a cool topic!",
|
||||||
avatarURL: .picturesDirectory))
|
avatarURL: .picturesDirectory,
|
||||||
let coordinator = RoomDetailsEditScreenCoordinator(parameters: .init(accountOwner: RoomMemberProxyMock.mockOwner(allowedStateEvents: allowedStateEvents),
|
members: members))
|
||||||
|
let coordinator = RoomDetailsEditScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
navigationStackCoordinator: navigationStackCoordinator,
|
navigationStackCoordinator: navigationStackCoordinator,
|
||||||
roomProxy: roomProxy,
|
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
orientationManager: OrientationManagerMock()))
|
orientationManager: OrientationManagerMock()))
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
@@ -734,6 +738,7 @@ class MockScreen: Identifiable {
|
|||||||
let coordinator = ReportContentScreenCoordinator(parameters: .init(eventID: "test",
|
let coordinator = ReportContentScreenCoordinator(parameters: .init(eventID: "test",
|
||||||
senderID: RoomMemberProxyMock.mockAlice.userID,
|
senderID: RoomMemberProxyMock.mockAlice.userID,
|
||||||
roomProxy: RoomProxyMock(with: .init(name: "test")),
|
roomProxy: RoomProxyMock(with: .init(name: "test")),
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
userIndicatorController: UserIndicatorControllerMock()))
|
userIndicatorController: UserIndicatorControllerMock()))
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
return navigationStackCoordinator
|
return navigationStackCoordinator
|
||||||
@@ -774,8 +779,9 @@ class MockScreen: Identifiable {
|
|||||||
roomProxy.getMemberUserIDReturnValue = .success(member)
|
roomProxy.getMemberUserIDReturnValue = .success(member)
|
||||||
|
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: .init(userID: member.userID,
|
||||||
userID: member.userID,
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
@@ -786,8 +792,9 @@ class MockScreen: Identifiable {
|
|||||||
roomProxy.getMemberUserIDReturnValue = .success(member)
|
roomProxy.getMemberUserIDReturnValue = .success(member)
|
||||||
|
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: .init(userID: member.userID,
|
||||||
userID: member.userID,
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
@@ -798,8 +805,9 @@ class MockScreen: Identifiable {
|
|||||||
roomProxy.getMemberUserIDReturnValue = .success(member)
|
roomProxy.getMemberUserIDReturnValue = .success(member)
|
||||||
|
|
||||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||||
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy,
|
let coordinator = RoomMemberDetailsScreenCoordinator(parameters: .init(userID: member.userID,
|
||||||
userID: member.userID,
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
userIndicatorController: ServiceLocator.shared.userIndicatorController))
|
||||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
|||||||
cancellables.removeAll()
|
cancellables.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserSuggestons() async throws {
|
func testUserSuggestions() async throws {
|
||||||
let alice: RoomMemberProxyMock = .mockAlice
|
let alice: RoomMemberProxyMock = .mockAlice
|
||||||
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
||||||
let roomProxyMock = RoomProxyMock(with: .init(name: "test", members: members))
|
let roomProxyMock = RoomProxyMock(with: .init(name: "test", members: members))
|
||||||
@@ -64,7 +64,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
|||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testUserSuggestonsIncludingAllUsers() async throws {
|
func testUserSuggestionsIncludingAllUsers() async throws {
|
||||||
let alice: RoomMemberProxyMock = .mockAlice
|
let alice: RoomMemberProxyMock = .mockAlice
|
||||||
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
||||||
let roomProxyMock = RoomProxyMock(with: .init(name: "test", members: members, canUserTriggerRoomNotification: true))
|
let roomProxyMock = RoomProxyMock(with: .init(name: "test", members: members, canUserTriggerRoomNotification: true))
|
||||||
|
|||||||
@@ -27,9 +27,11 @@ class ReportContentScreenViewModelTests: XCTestCase {
|
|||||||
// Given the report content view for some content.
|
// Given the report content view for some content.
|
||||||
let roomProxy = RoomProxyMock(with: .init(name: "test"))
|
let roomProxy = RoomProxyMock(with: .init(name: "test"))
|
||||||
roomProxy.reportContentReasonReturnValue = .success(())
|
roomProxy.reportContentReasonReturnValue = .success(())
|
||||||
|
let clientProxy = ClientProxyMock(.init())
|
||||||
let viewModel = ReportContentScreenViewModel(eventID: eventID,
|
let viewModel = ReportContentScreenViewModel(eventID: eventID,
|
||||||
senderID: senderID,
|
senderID: senderID,
|
||||||
roomProxy: roomProxy)
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: clientProxy)
|
||||||
|
|
||||||
// When reporting the content without ignoring the user.
|
// When reporting the content without ignoring the user.
|
||||||
viewModel.state.bindings.reasonText = reportReason
|
viewModel.state.bindings.reasonText = reportReason
|
||||||
@@ -46,18 +48,19 @@ class ReportContentScreenViewModelTests: XCTestCase {
|
|||||||
XCTAssertEqual(roomProxy.reportContentReasonCallsCount, 1, "The content should always be reported.")
|
XCTAssertEqual(roomProxy.reportContentReasonCallsCount, 1, "The content should always be reported.")
|
||||||
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.eventID, eventID, "The event ID should match the content being reported.")
|
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.eventID, eventID, "The event ID should match the content being reported.")
|
||||||
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.reason, reportReason, "The reason should match the user input.")
|
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.reason, reportReason, "The reason should match the user input.")
|
||||||
XCTAssertEqual(roomProxy.ignoreUserCallsCount, 0, "A call to ignore a user should not have been made.")
|
XCTAssertEqual(clientProxy.ignoreUserCallsCount, 0, "A call to ignore a user should not have been made.")
|
||||||
XCTAssertNil(roomProxy.ignoreUserReceivedUserID, "The sender shouldn't have been ignored.")
|
XCTAssertNil(clientProxy.ignoreUserReceivedUserID, "The sender shouldn't have been ignored.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testReportIgnoringSender() async throws {
|
func testReportIgnoringSender() async throws {
|
||||||
// Given the report content view for some content.
|
// Given the report content view for some content.
|
||||||
let roomProxy = RoomProxyMock(with: .init(name: "test"))
|
let roomProxy = RoomProxyMock(with: .init(name: "test"))
|
||||||
roomProxy.reportContentReasonReturnValue = .success(())
|
roomProxy.reportContentReasonReturnValue = .success(())
|
||||||
roomProxy.ignoreUserReturnValue = .success(())
|
let clientProxy = ClientProxyMock(.init())
|
||||||
let viewModel = ReportContentScreenViewModel(eventID: eventID,
|
let viewModel = ReportContentScreenViewModel(eventID: eventID,
|
||||||
senderID: senderID,
|
senderID: senderID,
|
||||||
roomProxy: roomProxy)
|
roomProxy: roomProxy,
|
||||||
|
clientProxy: clientProxy)
|
||||||
|
|
||||||
// When reporting the content and also ignoring the user.
|
// When reporting the content and also ignoring the user.
|
||||||
viewModel.state.bindings.reasonText = reportReason
|
viewModel.state.bindings.reasonText = reportReason
|
||||||
@@ -75,7 +78,7 @@ class ReportContentScreenViewModelTests: XCTestCase {
|
|||||||
XCTAssertEqual(roomProxy.reportContentReasonCallsCount, 1, "The content should always be reported.")
|
XCTAssertEqual(roomProxy.reportContentReasonCallsCount, 1, "The content should always be reported.")
|
||||||
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.eventID, eventID, "The event ID should match the content being reported.")
|
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.eventID, eventID, "The event ID should match the content being reported.")
|
||||||
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.reason, reportReason, "The reason should match the user input.")
|
XCTAssertEqual(roomProxy.reportContentReasonReceivedArguments?.reason, reportReason, "The reason should match the user input.")
|
||||||
XCTAssertEqual(roomProxy.ignoreUserCallsCount, 1, "A call should have been made to ignore the sender.")
|
XCTAssertEqual(clientProxy.ignoreUserCallsCount, 1, "A call should have been made to ignore the sender.")
|
||||||
XCTAssertEqual(roomProxy.ignoreUserReceivedUserID, senderID, "The ignored user ID should match the sender.")
|
XCTAssertEqual(clientProxy.ignoreUserReceivedUserID, senderID, "The ignored user ID should match the sender.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,61 +30,57 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCannotSaveOnLanding() {
|
func testCannotSaveOnLanding() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
XCTAssertFalse(context.viewState.canSave)
|
XCTAssertFalse(context.viewState.canSave)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCanEdit() {
|
func testCanEdit() async throws {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
|
let deferred = deferFulfillment(context.$viewState) { $0.canEditName }
|
||||||
|
try await deferred.fulfill()
|
||||||
|
|
||||||
XCTAssertTrue(context.viewState.canEditAvatar)
|
XCTAssertTrue(context.viewState.canEditAvatar)
|
||||||
XCTAssertTrue(context.viewState.canEditName)
|
XCTAssertTrue(context.viewState.canEditName)
|
||||||
XCTAssertTrue(context.viewState.canEditTopic)
|
XCTAssertTrue(context.viewState.canEditTopic)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCannotEdit() {
|
func testCannotEdit() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: []),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMe]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
XCTAssertFalse(context.viewState.canEditAvatar)
|
XCTAssertFalse(context.viewState.canEditAvatar)
|
||||||
XCTAssertFalse(context.viewState.canEditName)
|
XCTAssertFalse(context.viewState.canEditName)
|
||||||
XCTAssertFalse(context.viewState.canEditTopic)
|
XCTAssertFalse(context.viewState.canEditTopic)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testNameDidChange() {
|
func testNameDidChange() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
context.name = "name"
|
context.name = "name"
|
||||||
XCTAssertTrue(context.viewState.nameDidChange)
|
XCTAssertTrue(context.viewState.nameDidChange)
|
||||||
XCTAssertTrue(context.viewState.canSave)
|
XCTAssertTrue(context.viewState.canSave)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTopicDidChange() {
|
func testTopicDidChange() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
context.topic = "topic"
|
context.topic = "topic"
|
||||||
XCTAssertTrue(context.viewState.topicDidChange)
|
XCTAssertTrue(context.viewState.topicDidChange)
|
||||||
XCTAssertTrue(context.viewState.canSave)
|
XCTAssertTrue(context.viewState.canSave)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAvatarDidChange() {
|
func testAvatarDidChange() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory, members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory))
|
|
||||||
context.send(viewAction: .removeImage)
|
context.send(viewAction: .removeImage)
|
||||||
XCTAssertTrue(context.viewState.avatarDidChange)
|
XCTAssertTrue(context.viewState.avatarDidChange)
|
||||||
XCTAssertTrue(context.viewState.canSave)
|
XCTAssertTrue(context.viewState.canSave)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEmptyNameCannotBeSaved() {
|
func testEmptyNameCannotBeSaved() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
context.name = ""
|
context.name = ""
|
||||||
XCTAssertFalse(context.viewState.canSave)
|
XCTAssertFalse(context.viewState.canSave)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSaveShowsSheet() {
|
func testSaveShowsSheet() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
context.name = "name"
|
context.name = "name"
|
||||||
XCTAssertFalse(context.showMediaSheet)
|
XCTAssertFalse(context.showMediaSheet)
|
||||||
context.send(viewAction: .presentMediaSource)
|
context.send(viewAction: .presentMediaSource)
|
||||||
@@ -92,8 +88,7 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSaveTriggersViewModelAction() async throws {
|
func testSaveTriggersViewModelAction() async throws {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
|
|
||||||
let deferred = deferFulfillment(viewModel.actions) { action in
|
let deferred = deferFulfillment(viewModel.actions) { action in
|
||||||
action == .saveFinished
|
action == .saveFinished
|
||||||
@@ -107,16 +102,14 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testErrorShownOnFailedFetchOfMedia() async throws {
|
func testErrorShownOnFailedFetchOfMedia() async throws {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room"))
|
|
||||||
viewModel.didSelectMediaUrl(url: .picturesDirectory)
|
viewModel.didSelectMediaUrl(url: .picturesDirectory)
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
try? await Task.sleep(for: .milliseconds(100))
|
||||||
XCTAssertNotNil(userIndicatorController.alertInfo)
|
XCTAssertNotNil(userIndicatorController.alertInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDeleteAvatar() {
|
func testDeleteAvatar() {
|
||||||
setupViewModel(accountOwner: .mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]),
|
setupViewModel(roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory, members: [.mockMeAdmin]))
|
||||||
roomProxyConfiguration: .init(name: "Some room", avatarURL: .picturesDirectory))
|
|
||||||
XCTAssertNotNil(context.viewState.avatarURL)
|
XCTAssertNotNil(context.viewState.avatarURL)
|
||||||
context.send(viewAction: .removeImage)
|
context.send(viewAction: .removeImage)
|
||||||
XCTAssertNil(context.viewState.avatarURL)
|
XCTAssertNil(context.viewState.avatarURL)
|
||||||
@@ -124,11 +117,10 @@ class RoomDetailsEditScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func setupViewModel(accountOwner: RoomMemberProxyMock, roomProxyConfiguration: RoomProxyMockConfiguration) {
|
private func setupViewModel(roomProxyConfiguration: RoomProxyMockConfiguration) {
|
||||||
userIndicatorController = UserIndicatorControllerMock.default
|
userIndicatorController = UserIndicatorControllerMock.default
|
||||||
viewModel = .init(accountOwner: accountOwner,
|
viewModel = .init(roomProxy: RoomProxyMock(with: roomProxyConfiguration),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
roomProxy: RoomProxyMock(with: roomProxyConfiguration),
|
|
||||||
userIndicatorController: userIndicatorController)
|
userIndicatorController: userIndicatorController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
cancellables.removeAll()
|
cancellables.removeAll()
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test"))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test"))
|
||||||
notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
|
notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -48,8 +48,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
func testLeaveRoomTappedWhenPublic() async throws {
|
func testLeaveRoomTappedWhenPublic() async throws {
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -70,8 +70,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
func testLeaveRoomTappedWhenRoomNotPublic() async throws {
|
func testLeaveRoomTappedWhenRoomNotPublic() async throws {
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: false, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: false, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -93,8 +93,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
func testLeaveRoomTappedWithLessThanTwoMembers() async {
|
func testLeaveRoomTappedWithLessThanTwoMembers() async {
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockAlice]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockAlice]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: false, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: false, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -146,8 +146,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
let recipient = RoomMemberProxyMock.mockDan
|
let recipient = RoomMemberProxyMock.mockDan
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -166,15 +166,11 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testIgnoreSuccess() async throws {
|
func testIgnoreSuccess() async throws {
|
||||||
let recipient = RoomMemberProxyMock.mockDan
|
let recipient = RoomMemberProxyMock.mockDan
|
||||||
recipient.ignoreUserClosure = {
|
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
|
||||||
return .success(())
|
|
||||||
}
|
|
||||||
|
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -203,14 +199,12 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testIgnoreFailure() async throws {
|
func testIgnoreFailure() async throws {
|
||||||
let recipient = RoomMemberProxyMock.mockDan
|
let recipient = RoomMemberProxyMock.mockDan
|
||||||
recipient.ignoreUserClosure = {
|
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
|
||||||
return .failure(.ignoreUserFailed)
|
|
||||||
}
|
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
||||||
|
let clientProxy = ClientProxyMock(.init())
|
||||||
|
clientProxy.ignoreUserReturnValue = .failure(.failedIgnoringUser)
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: clientProxy,
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -240,14 +234,10 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testUnignoreSuccess() async throws {
|
func testUnignoreSuccess() async throws {
|
||||||
let recipient = RoomMemberProxyMock.mockIgnored
|
let recipient = RoomMemberProxyMock.mockIgnored
|
||||||
recipient.unignoreUserClosure = {
|
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
|
||||||
return .success(())
|
|
||||||
}
|
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -276,14 +266,12 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testUnignoreFailure() async throws {
|
func testUnignoreFailure() async throws {
|
||||||
let recipient = RoomMemberProxyMock.mockIgnored
|
let recipient = RoomMemberProxyMock.mockIgnored
|
||||||
recipient.unignoreUserClosure = {
|
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
|
||||||
return .failure(.unignoreUserFailed)
|
|
||||||
}
|
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, recipient]
|
||||||
|
let clientProxy = ClientProxyMock(.init())
|
||||||
|
clientProxy.unignoreUserReturnValue = .failure(.failedUnignoringUser)
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: clientProxy,
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -312,13 +300,13 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCannotInvitePeople() async {
|
func testCannotInvitePeople() async {
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockBob, .mockAlice]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockAlice]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test",
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test",
|
||||||
isPublic: true,
|
isPublic: true,
|
||||||
members: mockedMembers,
|
members: mockedMembers,
|
||||||
memberForID: .mockOwner(allowedStateEvents: [], canInviteUsers: false)))
|
canUserInvite: false))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -334,8 +322,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
func testInvitePeople() async {
|
func testInvitePeople() async {
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: true, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isPublic: true, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -365,11 +353,13 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCanEditAvatar() async {
|
func testCanEditAvatar() async {
|
||||||
let owner: RoomMemberProxyMock = .mockOwner(allowedStateEvents: [.roomAvatar])
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice]
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [owner, .mockBob, .mockAlice]
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers))
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers, memberForID: owner))
|
roomProxyMock.canUserUserIDSendStateEventClosure = { _, event in
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
.success(event == .roomAvatar)
|
||||||
roomProxy: roomProxyMock,
|
}
|
||||||
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -386,11 +376,13 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCanEditName() async {
|
func testCanEditName() async {
|
||||||
let owner: RoomMemberProxyMock = .mockOwner(allowedStateEvents: [.roomName])
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice]
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [owner, .mockBob, .mockAlice]
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers))
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers, memberForID: owner))
|
roomProxyMock.canUserUserIDSendStateEventClosure = { _, event in
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
.success(event == .roomName)
|
||||||
roomProxy: roomProxyMock,
|
}
|
||||||
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -407,11 +399,13 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCanEditTopic() async {
|
func testCanEditTopic() async {
|
||||||
let owner: RoomMemberProxyMock = .mockOwner(allowedStateEvents: [.roomTopic])
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice]
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [owner, .mockBob, .mockAlice]
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers))
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers, memberForID: owner))
|
roomProxyMock.canUserUserIDSendStateEventClosure = { _, event in
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
.success(event == .roomTopic)
|
||||||
roomProxy: roomProxyMock,
|
}
|
||||||
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -428,11 +422,10 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCannotEditRoom() async {
|
func testCannotEditRoom() async {
|
||||||
let owner: RoomMemberProxyMock = .mockOwner(allowedStateEvents: [])
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMe, .mockBob, .mockAlice]
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [owner, .mockBob, .mockAlice]
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers))
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: false, isPublic: false, members: mockedMembers, memberForID: owner))
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
clientProxy: ClientProxyMock(.init()),
|
||||||
roomProxy: roomProxyMock,
|
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -449,10 +442,10 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCannotEditDirectRoom() async {
|
func testCannotEditDirectRoom() async {
|
||||||
let mockedMembers: [RoomMemberProxyMock] = [.mockOwner(allowedStateEvents: [.roomAvatar, .roomName, .roomTopic]), .mockBob, .mockAlice]
|
let mockedMembers: [RoomMemberProxyMock] = [.mockMeAdmin, .mockBob, .mockAlice]
|
||||||
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isPublic: false, members: mockedMembers))
|
roomProxyMock = RoomProxyMock(with: .init(name: "Test", isDirect: true, isPublic: false, members: mockedMembers))
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
@@ -469,8 +462,8 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testNotificationLoadingSettingsFailure() async throws {
|
func testNotificationLoadingSettingsFailure() async throws {
|
||||||
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error")
|
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error")
|
||||||
viewModel = RoomDetailsScreenViewModel(accountUserID: "@owner:somewhere.com",
|
viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||||
roomProxy: roomProxyMock,
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
analyticsService: ServiceLocator.shared.analytics,
|
analyticsService: ServiceLocator.shared.analytics,
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||||
|
|||||||
@@ -35,8 +35,9 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testInitialState() async throws {
|
func testInitialState() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockAlice
|
roomMemberProxyMock = RoomMemberProxyMock.mockAlice
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
userID: roomMemberProxyMock.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
@@ -50,12 +51,9 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testIgnoreSuccess() async throws {
|
func testIgnoreSuccess() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockAlice
|
roomMemberProxyMock = RoomMemberProxyMock.mockAlice
|
||||||
roomMemberProxyMock.ignoreUserClosure = {
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
roomProxy: roomProxyMock,
|
||||||
return .success(())
|
clientProxy: ClientProxyMock(.init()),
|
||||||
}
|
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
|
||||||
userID: roomMemberProxyMock.userID,
|
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
@@ -88,12 +86,11 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testIgnoreFailure() async throws {
|
func testIgnoreFailure() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockAlice
|
roomMemberProxyMock = RoomMemberProxyMock.mockAlice
|
||||||
roomMemberProxyMock.ignoreUserClosure = {
|
let clientProxy = ClientProxyMock(.init())
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
clientProxy.ignoreUserReturnValue = .failure(.failedIgnoringUser)
|
||||||
return .failure(.ignoreUserFailed)
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
}
|
roomProxy: roomProxyMock,
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
clientProxy: clientProxy,
|
||||||
userID: roomMemberProxyMock.userID,
|
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
@@ -126,13 +123,10 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testUnignoreSuccess() async throws {
|
func testUnignoreSuccess() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockIgnored
|
roomMemberProxyMock = RoomMemberProxyMock.mockIgnored
|
||||||
roomMemberProxyMock.unignoreUserClosure = {
|
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
|
||||||
return .success(())
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
userID: roomMemberProxyMock.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
@@ -163,12 +157,11 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testUnignoreFailure() async throws {
|
func testUnignoreFailure() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockIgnored
|
roomMemberProxyMock = RoomMemberProxyMock.mockIgnored
|
||||||
roomMemberProxyMock.unignoreUserClosure = {
|
let clientProxy = ClientProxyMock(.init())
|
||||||
try? await Task.sleep(for: .milliseconds(100))
|
clientProxy.unignoreUserReturnValue = .failure(.failedUnignoringUser)
|
||||||
return .failure(.unignoreUserFailed)
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
}
|
roomProxy: roomProxyMock,
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
clientProxy: clientProxy,
|
||||||
userID: roomMemberProxyMock.userID,
|
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
@@ -201,8 +194,9 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testInitialStateAccountOwner() async throws {
|
func testInitialStateAccountOwner() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockMe
|
roomMemberProxyMock = RoomMemberProxyMock.mockMe
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
userID: roomMemberProxyMock.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
@@ -216,8 +210,9 @@ class RoomMemberDetailsViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
func testInitialStateIgnoredUser() async throws {
|
func testInitialStateIgnoredUser() async throws {
|
||||||
roomMemberProxyMock = RoomMemberProxyMock.mockIgnored
|
roomMemberProxyMock = RoomMemberProxyMock.mockIgnored
|
||||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
viewModel = RoomMemberDetailsScreenViewModel(userID: roomMemberProxyMock.userID,
|
||||||
userID: roomMemberProxyMock.userID,
|
roomProxy: roomProxyMock,
|
||||||
|
clientProxy: ClientProxyMock(.init()),
|
||||||
mediaProvider: MockMediaProvider(),
|
mediaProvider: MockMediaProvider(),
|
||||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ packages:
|
|||||||
# Element/Matrix dependencies
|
# Element/Matrix dependencies
|
||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
url: https://github.com/matrix-org/matrix-rust-components-swift
|
url: https://github.com/matrix-org/matrix-rust-components-swift
|
||||||
exactVersion: 1.1.44
|
exactVersion: 1.1.45
|
||||||
# path: ../matrix-rust-sdk
|
# path: ../matrix-rust-sdk
|
||||||
Compound:
|
Compound:
|
||||||
url: https://github.com/element-hq/compound-ios
|
url: https://github.com/element-hq/compound-ios
|
||||||
|
|||||||
Reference in New Issue
Block a user