mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Update the SDK and handle breaking changes. (#2527)
This commit is contained in:
@@ -28,7 +28,7 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
||||
self.roomProxy = roomProxy
|
||||
suggestionsPublisher = suggestionTriggerSubject
|
||||
.combineLatest(roomProxy.membersPublisher)
|
||||
.map { [weak self] suggestionPattern, members -> [SuggestionItem] in
|
||||
.map { [weak self, ownUserID = roomProxy.ownUserID] suggestionPattern, members -> [SuggestionItem] in
|
||||
guard let self,
|
||||
let suggestionPattern else {
|
||||
return []
|
||||
@@ -38,7 +38,7 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
||||
case .user:
|
||||
var membersSuggestion = members
|
||||
.compactMap { member -> SuggestionItem? in
|
||||
guard !member.isAccountOwner,
|
||||
guard member.userID != ownUserID,
|
||||
member.membership == .join,
|
||||
Self.isIncluded(searchText: suggestionPattern.text, userID: member.userID, displayName: member.displayName) else {
|
||||
return nil
|
||||
|
||||
@@ -21,6 +21,7 @@ struct ReportContentScreenCoordinatorParameters {
|
||||
let eventID: String
|
||||
let senderID: String
|
||||
let roomProxy: RoomProxyProtocol
|
||||
let clientProxy: ClientProxyProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
}
|
||||
|
||||
@@ -42,7 +43,10 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
|
||||
init(parameters: ReportContentScreenCoordinatorParameters) {
|
||||
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
|
||||
@@ -55,9 +59,9 @@ final class ReportContentScreenCoordinator: CoordinatorProtocol {
|
||||
switch action {
|
||||
case .submitStarted:
|
||||
startLoading()
|
||||
case let .submitFailed(error):
|
||||
case let .submitFailed(message):
|
||||
stopLoading()
|
||||
showError(description: error.localizedDescription)
|
||||
showError(description: message)
|
||||
case .submitFinished:
|
||||
stopLoading()
|
||||
actionsSubject.send(.finish)
|
||||
|
||||
@@ -20,7 +20,7 @@ enum ReportContentScreenViewModelAction: Equatable {
|
||||
case cancel
|
||||
case submitStarted
|
||||
case submitFinished
|
||||
case submitFailed(error: RoomProxyError)
|
||||
case submitFailed(message: String)
|
||||
}
|
||||
|
||||
struct ReportContentScreenViewState: BindableState {
|
||||
|
||||
@@ -23,16 +23,18 @@ class ReportContentScreenViewModel: ReportContentScreenViewModelType, ReportCont
|
||||
private let eventID: String
|
||||
private let senderID: String
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let clientProxy: ClientProxyProtocol
|
||||
private let actionsSubject: PassthroughSubject<ReportContentScreenViewModelAction, Never> = .init()
|
||||
|
||||
var actions: AnyPublisher<ReportContentScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(eventID: String, senderID: String, roomProxy: RoomProxyProtocol) {
|
||||
init(eventID: String, senderID: String, roomProxy: RoomProxyProtocol, clientProxy: ClientProxyProtocol) {
|
||||
self.eventID = eventID
|
||||
self.senderID = senderID
|
||||
self.roomProxy = roomProxy
|
||||
self.clientProxy = clientProxy
|
||||
|
||||
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) {
|
||||
MXLog.error("Submit Report Content failed: \(error)")
|
||||
actionsSubject.send(.submitFailed(error: error))
|
||||
actionsSubject.send(.submitFailed(message: error.localizedDescription))
|
||||
return
|
||||
}
|
||||
|
||||
// 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)")
|
||||
actionsSubject.send(.submitFailed(error: error))
|
||||
actionsSubject.send(.submitFailed(message: error.localizedDescription))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ struct ReportContentScreen: View {
|
||||
struct ReportContentScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = ReportContentScreenViewModel(eventID: "",
|
||||
senderID: "",
|
||||
roomProxy: RoomProxyMock(with: .init()))
|
||||
roomProxy: RoomProxyMock(with: .init()),
|
||||
clientProxy: ClientProxyMock(.init()))
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
|
||||
+2
-4
@@ -18,10 +18,9 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct RoomDetailsEditScreenCoordinatorParameters {
|
||||
let accountOwner: RoomMemberProxyProtocol
|
||||
let roomProxy: RoomProxyProtocol
|
||||
let mediaProvider: MediaProviderProtocol
|
||||
weak var navigationStackCoordinator: NavigationStackCoordinator?
|
||||
let roomProxy: RoomProxyProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
let orientationManager: OrientationManagerProtocol
|
||||
}
|
||||
@@ -43,9 +42,8 @@ final class RoomDetailsEditScreenCoordinator: CoordinatorProtocol {
|
||||
init(parameters: RoomDetailsEditScreenCoordinatorParameters) {
|
||||
self.parameters = parameters
|
||||
|
||||
viewModel = RoomDetailsEditScreenViewModel(accountOwner: parameters.accountOwner,
|
||||
viewModel = RoomDetailsEditScreenViewModel(roomProxy: parameters.roomProxy,
|
||||
mediaProvider: parameters.mediaProvider,
|
||||
roomProxy: parameters.roomProxy,
|
||||
userIndicatorController: parameters.userIndicatorController)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ struct RoomDetailsEditScreenViewState: BindableState {
|
||||
let initialAvatarURL: URL?
|
||||
let initialName: String
|
||||
let initialTopic: String
|
||||
let canEditAvatar: Bool
|
||||
let canEditName: Bool
|
||||
let canEditTopic: Bool
|
||||
var canEditAvatar = false
|
||||
var canEditName = false
|
||||
var canEditTopic = false
|
||||
var avatarURL: URL?
|
||||
var localMedia: MediaInfo?
|
||||
|
||||
|
||||
@@ -29,9 +29,8 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(accountOwner: RoomMemberProxyProtocol,
|
||||
init(roomProxy: RoomProxyProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
roomProxy: RoomProxyProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.roomProxy = roomProxy
|
||||
self.userIndicatorController = userIndicatorController
|
||||
@@ -44,11 +43,15 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe
|
||||
initialAvatarURL: roomAvatar,
|
||||
initialName: roomName ?? "",
|
||||
initialTopic: roomTopic ?? "",
|
||||
canEditAvatar: accountOwner.canSendStateEvent(type: .roomAvatar),
|
||||
canEditName: accountOwner.canSendStateEvent(type: .roomName),
|
||||
canEditTopic: accountOwner.canSendStateEvent(type: .roomTopic),
|
||||
avatarURL: roomAvatar,
|
||||
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
|
||||
|
||||
@@ -156,16 +156,18 @@ struct RoomDetailsEditScreen: View {
|
||||
// MARK: - Previews
|
||||
|
||||
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(),
|
||||
roomProxy: RoomProxyMock(with: .init(id: "test_id", name: "Room")),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
|
||||
static let readOnlyViewModel = {
|
||||
let accountOwner = RoomMemberProxyMock.mockOwner(allowedStateEvents: [])
|
||||
return RoomDetailsEditScreenViewModel(accountOwner: accountOwner,
|
||||
let accountOwner = RoomMemberProxyMock.mockMe
|
||||
return RoomDetailsEditScreenViewModel(roomProxy: RoomProxyMock(with: .init(id: "test_id",
|
||||
name: "Room",
|
||||
members: [.mockMe])),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
roomProxy: RoomProxyMock(with: .init(id: "test_id", name: "Room")),
|
||||
userIndicatorController: UserIndicatorControllerMock.default)
|
||||
}()
|
||||
|
||||
@@ -174,10 +176,12 @@ struct RoomDetailsEditScreen_Previews: PreviewProvider, TestablePreview {
|
||||
RoomDetailsEditScreen(context: viewModel.context)
|
||||
}
|
||||
.previewDisplayName("Normal")
|
||||
.snapshot(delay: 0.1)
|
||||
|
||||
NavigationStack {
|
||||
RoomDetailsEditScreen(context: readOnlyViewModel.context)
|
||||
}
|
||||
.previewDisplayName("Read only")
|
||||
.snapshot(delay: 0.1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct RoomDetailsScreenCoordinatorParameters {
|
||||
let accountUserID: String
|
||||
let roomProxy: RoomProxyProtocol
|
||||
let clientProxy: ClientProxyProtocol
|
||||
let mediaProvider: MediaProviderProtocol
|
||||
let analyticsService: AnalyticsService
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
@@ -30,7 +30,7 @@ struct RoomDetailsScreenCoordinatorParameters {
|
||||
enum RoomDetailsScreenCoordinatorAction {
|
||||
case leftRoom
|
||||
case presentRoomMembersList
|
||||
case presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol)
|
||||
case presentRoomDetailsEditScreen
|
||||
case presentNotificationSettingsScreen
|
||||
case presentInviteUsersScreen
|
||||
case presentPollsHistory
|
||||
@@ -47,8 +47,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: RoomDetailsScreenCoordinatorParameters) {
|
||||
viewModel = RoomDetailsScreenViewModel(accountUserID: parameters.accountUserID,
|
||||
roomProxy: parameters.roomProxy,
|
||||
viewModel = RoomDetailsScreenViewModel(roomProxy: parameters.roomProxy,
|
||||
clientProxy: parameters.clientProxy,
|
||||
mediaProvider: parameters.mediaProvider,
|
||||
analyticsService: parameters.analyticsService,
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
@@ -70,8 +70,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
||||
actionsSubject.send(.presentInviteUsersScreen)
|
||||
case .leftRoom:
|
||||
actionsSubject.send(.leftRoom)
|
||||
case .requestEditDetailsPresentation(let accountOwner):
|
||||
actionsSubject.send(.presentRoomDetailsEditScreen(accountOwner: accountOwner))
|
||||
case .requestEditDetailsPresentation:
|
||||
actionsSubject.send(.presentRoomDetailsEditScreen)
|
||||
case .requestNotificationSettingsPresentation:
|
||||
actionsSubject.send(.presentNotificationSettingsScreen)
|
||||
case .requestPollsHistoryPresentation:
|
||||
|
||||
@@ -26,7 +26,7 @@ enum RoomDetailsScreenViewModelAction {
|
||||
case requestMemberDetailsPresentation
|
||||
case requestInvitePeoplePresentation
|
||||
case leftRoom
|
||||
case requestEditDetailsPresentation(RoomMemberProxyProtocol)
|
||||
case requestEditDetailsPresentation
|
||||
case requestPollsHistoryPresentation
|
||||
}
|
||||
|
||||
|
||||
@@ -20,18 +20,14 @@ import SwiftUI
|
||||
typealias RoomDetailsScreenViewModelType = StateStoreViewModel<RoomDetailsScreenViewState, RoomDetailsScreenViewAction>
|
||||
|
||||
class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScreenViewModelProtocol {
|
||||
private let accountUserID: String
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let clientProxy: ClientProxyProtocol
|
||||
private let analyticsService: AnalyticsService
|
||||
private let mediaProvider: MediaProviderProtocol
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let notificationSettingsProxy: NotificationSettingsProxyProtocol
|
||||
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||
|
||||
private var accountOwner: RoomMemberProxyProtocol? {
|
||||
didSet { updatePowerLevelPermissions() }
|
||||
}
|
||||
|
||||
private var dmRecipient: RoomMemberProxyProtocol?
|
||||
|
||||
private var actionsSubject: PassthroughSubject<RoomDetailsScreenViewModelAction, Never> = .init()
|
||||
@@ -40,15 +36,15 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(accountUserID: String,
|
||||
roomProxy: RoomProxyProtocol,
|
||||
init(roomProxy: RoomProxyProtocol,
|
||||
clientProxy: ClientProxyProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
analyticsService: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
notificationSettingsProxy: NotificationSettingsProxyProtocol,
|
||||
attributedStringBuilder: AttributedStringBuilderProtocol) {
|
||||
self.accountUserID = accountUserID
|
||||
self.roomProxy = roomProxy
|
||||
self.clientProxy = clientProxy
|
||||
self.mediaProvider = mediaProvider
|
||||
self.analyticsService = analyticsService
|
||||
self.userIndicatorController = userIndicatorController
|
||||
@@ -69,9 +65,10 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
imageProvider: mediaProvider)
|
||||
|
||||
updateRoomInfo()
|
||||
Task { await updatePowerLevelPermissions() }
|
||||
|
||||
setupRoomSubscription()
|
||||
fetchMembers()
|
||||
Task { await fetchMembersIfNeeded() }
|
||||
|
||||
setupNotificationSettingsSubscription()
|
||||
fetchNotificationSettings()
|
||||
@@ -103,11 +100,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
case .processTapUnignore:
|
||||
state.bindings.ignoreUserRoomAlertItem = .init(action: .unignore)
|
||||
case .processTapEdit, .processTapAddTopic:
|
||||
guard let accountOwner else {
|
||||
MXLog.error("Missing account owner when presenting the room's edit details screen")
|
||||
return
|
||||
}
|
||||
actionsSubject.send(.requestEditDetailsPresentation(accountOwner))
|
||||
actionsSubject.send(.requestEditDetailsPresentation)
|
||||
case .ignoreConfirmed:
|
||||
Task { await ignore() }
|
||||
case .unignoreConfirmed:
|
||||
@@ -154,13 +147,6 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchMembers() {
|
||||
Task {
|
||||
await fetchMembersIfNeeded()
|
||||
await fetchAccountOwner()
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchMembersIfNeeded() async {
|
||||
// We need to fetch members just in 1-to-1 chat to get the member object for the other person
|
||||
guard roomProxy.isEncryptedOneToOneRoom else {
|
||||
@@ -169,9 +155,9 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
|
||||
roomProxy.membersPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] members in
|
||||
.sink { [weak self, ownUserID = roomProxy.ownUserID] members in
|
||||
guard let self else { return }
|
||||
let dmRecipient = members.first(where: { !$0.isAccountOwner })
|
||||
let dmRecipient = members.first(where: { $0.userID != ownUserID })
|
||||
self.dmRecipient = dmRecipient
|
||||
self.state.dmRecipient = dmRecipient.map(RoomMemberDetails.init(withProxy:))
|
||||
}
|
||||
@@ -180,20 +166,13 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
await roomProxy.updateMembers()
|
||||
}
|
||||
|
||||
private func fetchAccountOwner() async {
|
||||
switch await roomProxy.getMember(userID: accountUserID) {
|
||||
case .success(let member):
|
||||
accountOwner = member
|
||||
case .failure(let error):
|
||||
MXLog.error("Failed (error: \(error) to get account owner member with id: \(accountUserID), in room: \(roomProxy.id)")
|
||||
}
|
||||
}
|
||||
|
||||
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 updatePowerLevelPermissions() async {
|
||||
async let canInviteUsers = roomProxy.canUserInvite(userID: roomProxy.ownUserID) == .success(true)
|
||||
// Can't use async let because the mocks aren't thread safe when calling the same method 🤦♂️
|
||||
state.canEditRoomName = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomName) == .success(true)
|
||||
state.canEditRoomTopic = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomTopic) == .success(true)
|
||||
state.canEditRoomAvatar = await roomProxy.canUser(userID: roomProxy.ownUserID, sendStateEvent: .roomAvatar) == .success(true)
|
||||
state.canInviteUsers = await canInviteUsers
|
||||
}
|
||||
|
||||
private func setupNotificationSettingsSubscription() {
|
||||
@@ -280,8 +259,14 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
}
|
||||
|
||||
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
|
||||
let result = await dmRecipient?.ignoreUser()
|
||||
let result = await clientProxy.ignoreUser(dmUserID)
|
||||
state.isProcessingIgnoreRequest = false
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -289,14 +274,20 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
var dmRecipient = state.dmRecipient
|
||||
dmRecipient?.isIgnored = true
|
||||
state.dmRecipient = dmRecipient
|
||||
case .failure, .none:
|
||||
case .failure:
|
||||
state.bindings.alertInfo = .init(id: .unknown)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
let result = await dmRecipient?.unignoreUser()
|
||||
let result = await clientProxy.unignoreUser(dmUserID)
|
||||
state.isProcessingIgnoreRequest = false
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -304,7 +295,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
var dmRecipient = state.dmRecipient
|
||||
dmRecipient?.isIgnored = false
|
||||
state.dmRecipient = dmRecipient
|
||||
case .failure, .none:
|
||||
case .failure:
|
||||
state.bindings.alertInfo = .init(id: .unknown)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ struct RoomDetailsScreen: View {
|
||||
struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let genericRoomViewModel = {
|
||||
let members: [RoomMemberProxyMock] = [
|
||||
.mockMe,
|
||||
.mockMeAdmin,
|
||||
.mockAlice,
|
||||
.mockBob,
|
||||
.mockCharlie
|
||||
@@ -304,8 +304,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: notificationSettingsProxyMockConfiguration)
|
||||
let appSettings = AppSettings()
|
||||
|
||||
return RoomDetailsScreenViewModel(accountUserID: RoomMemberProxyMock.mockMe.userID,
|
||||
roomProxy: roomProxy,
|
||||
return RoomDetailsScreenViewModel(roomProxy: roomProxy,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
@@ -330,8 +330,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||
let appSettings = AppSettings()
|
||||
|
||||
return RoomDetailsScreenViewModel(accountUserID: RoomMemberProxyMock.mockMe.userID,
|
||||
roomProxy: roomProxy,
|
||||
return RoomDetailsScreenViewModel(roomProxy: roomProxy,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
@@ -342,7 +342,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static let simpleRoomViewModel = {
|
||||
let members: [RoomMemberProxyMock] = [
|
||||
.mockMe,
|
||||
.mockMeAdmin,
|
||||
.mockAlice,
|
||||
.mockBob,
|
||||
.mockCharlie
|
||||
@@ -355,8 +355,8 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let notificationSettingsProxy = NotificationSettingsProxyMock(with: .init())
|
||||
let appSettings = AppSettings()
|
||||
|
||||
return RoomDetailsScreenViewModel(accountUserID: RoomMemberProxyMock.mockMe.userID,
|
||||
roomProxy: roomProxy,
|
||||
return RoomDetailsScreenViewModel(roomProxy: roomProxy,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
analyticsService: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
|
||||
+5
-3
@@ -18,8 +18,9 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct RoomMemberDetailsScreenCoordinatorParameters {
|
||||
let roomProxy: RoomProxyProtocol
|
||||
let userID: String
|
||||
let roomProxy: RoomProxyProtocol
|
||||
let clientProxy: ClientProxyProtocol
|
||||
let mediaProvider: MediaProviderProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
}
|
||||
@@ -39,8 +40,9 @@ final class RoomMemberDetailsScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
init(parameters: RoomMemberDetailsScreenCoordinatorParameters) {
|
||||
viewModel = RoomMemberDetailsScreenViewModel(roomProxy: parameters.roomProxy,
|
||||
userID: parameters.userID,
|
||||
viewModel = RoomMemberDetailsScreenViewModel(userID: parameters.userID,
|
||||
roomProxy: parameters.roomProxy,
|
||||
clientProxy: parameters.clientProxy,
|
||||
mediaProvider: parameters.mediaProvider,
|
||||
userIndicatorController: parameters.userIndicatorController)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ enum RoomMemberDetailsScreenViewModelAction {
|
||||
struct RoomMemberDetailsScreenViewState: BindableState {
|
||||
let userID: String
|
||||
var memberDetails: RoomMemberDetails?
|
||||
var isOwnMemberDetails = false
|
||||
var isProcessingIgnoreRequest = false
|
||||
|
||||
var bindings: RoomMemberDetailsScreenViewStateBindings
|
||||
|
||||
+8
-4
@@ -21,6 +21,7 @@ typealias RoomMemberDetailsScreenViewModelType = StateStoreViewModel<RoomMemberD
|
||||
|
||||
class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, RoomMemberDetailsScreenViewModelProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let clientProxy: ClientProxyProtocol
|
||||
private let mediaProvider: MediaProviderProtocol
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
|
||||
@@ -32,11 +33,13 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
init(roomProxy: RoomProxyProtocol,
|
||||
userID: String,
|
||||
init(userID: String,
|
||||
roomProxy: RoomProxyProtocol,
|
||||
clientProxy: ClientProxyProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol) {
|
||||
self.roomProxy = roomProxy
|
||||
self.clientProxy = clientProxy
|
||||
self.mediaProvider = mediaProvider
|
||||
self.userIndicatorController = userIndicatorController
|
||||
|
||||
@@ -54,6 +57,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
case .success(let member):
|
||||
roomMemberProxy = member
|
||||
state.memberDetails = RoomMemberDetails(withProxy: member)
|
||||
state.isOwnMemberDetails = member.userID == roomProxy.ownUserID
|
||||
case .failure(let error):
|
||||
state.bindings.alertInfo = .init(id: .unknown)
|
||||
MXLog.error("[RoomFlowCoordinator] Failed to get member: \(error)")
|
||||
@@ -100,7 +104,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
}
|
||||
|
||||
state.isProcessingIgnoreRequest = true
|
||||
let result = await roomMemberProxy.ignoreUser()
|
||||
let result = await clientProxy.ignoreUser(roomMemberProxy.userID)
|
||||
state.isProcessingIgnoreRequest = false
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -118,7 +122,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
|
||||
}
|
||||
|
||||
state.isProcessingIgnoreRequest = true
|
||||
let result = await roomMemberProxy.unignoreUser()
|
||||
let result = await clientProxy.unignoreUser(roomMemberProxy.userID)
|
||||
state.isProcessingIgnoreRequest = false
|
||||
switch result {
|
||||
case .success:
|
||||
|
||||
+10
-8
@@ -36,8 +36,7 @@ struct RoomMemberDetailsScreen: View {
|
||||
Form {
|
||||
headerSection
|
||||
|
||||
if let memberDetails = context.viewState.memberDetails,
|
||||
!memberDetails.isAccountOwner {
|
||||
if context.viewState.memberDetails != nil, !context.viewState.isOwnMemberDetails {
|
||||
directChatSection
|
||||
blockUserSection
|
||||
}
|
||||
@@ -124,8 +123,9 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||
|
||||
return RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||
userID: member.userID,
|
||||
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||
roomProxy: roomProxyMock,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}()
|
||||
@@ -135,8 +135,9 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||
|
||||
return RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||
userID: member.userID,
|
||||
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||
roomProxy: roomProxyMock,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}()
|
||||
@@ -146,8 +147,9 @@ struct RoomMemberDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
let roomProxyMock = RoomProxyMock(with: .init(name: ""))
|
||||
roomProxyMock.getMemberUserIDReturnValue = .success(member)
|
||||
|
||||
return RoomMemberDetailsScreenViewModel(roomProxy: roomProxyMock,
|
||||
userID: member.userID,
|
||||
return RoomMemberDetailsScreenViewModel(userID: member.userID,
|
||||
roomProxy: roomProxyMock,
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
}()
|
||||
|
||||
@@ -106,11 +106,14 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
invitedMembers: roomMembersDetails.invitedMembers,
|
||||
bannedMembers: roomMembersDetails.bannedMembers,
|
||||
bindings: state.bindings)
|
||||
if let accountOwner = roomMembersDetails.accountOwner {
|
||||
self.state.canInviteUsers = accountOwner.canInviteUsers
|
||||
self.state.canKickUsers = accountOwner.canKickUsers
|
||||
self.state.canBanUsers = accountOwner.canBanUsers
|
||||
}
|
||||
|
||||
async let canInviteUsers = roomProxy.canUserInvite(userID: roomProxy.ownUserID)
|
||||
async let canKickUsers = roomProxy.canUserKick(userID: roomProxy.ownUserID)
|
||||
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 {
|
||||
state.bindings.mode = .members
|
||||
}
|
||||
@@ -125,13 +128,8 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
var invitedMembers: [RoomMemberDetails] = .init()
|
||||
var joinedMembers: [RoomMemberDetails] = .init()
|
||||
var bannedMembers: [RoomMemberDetails] = .init()
|
||||
var accountOwner: RoomMemberProxyProtocol?
|
||||
|
||||
for member in members {
|
||||
if accountOwner == nil, member.isAccountOwner {
|
||||
accountOwner = member
|
||||
}
|
||||
|
||||
switch member.membership {
|
||||
case .invite:
|
||||
invitedMembers.append(.init(withProxy: member))
|
||||
@@ -146,8 +144,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
|
||||
return .init(invitedMembers: invitedMembers,
|
||||
joinedMembers: joinedMembers,
|
||||
bannedMembers: bannedMembers.sorted { $0.id.localizedStandardCompare($1.id) == .orderedAscending }, // Re-sort ignoring display name.
|
||||
accountOwner: accountOwner)
|
||||
bannedMembers: bannedMembers.sorted { $0.id.localizedStandardCompare($1.id) == .orderedAscending }) // Re-sort ignoring display name.
|
||||
}
|
||||
.value
|
||||
}
|
||||
@@ -257,5 +254,4 @@ private struct RoomMembersDetails {
|
||||
var invitedMembers: [RoomMemberDetails]
|
||||
var joinedMembers: [RoomMemberDetails]
|
||||
var bannedMembers: [RoomMemberDetails]
|
||||
var accountOwner: RoomMemberProxyProtocol?
|
||||
}
|
||||
|
||||
@@ -142,10 +142,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
||||
initialMode: RoomMembersListScreenMode = .members) -> RoomMembersListScreenViewModel {
|
||||
let mockAdmin = RoomMemberProxyMock.mockAdmin
|
||||
|
||||
if isAdmin {
|
||||
mockAdmin.underlyingCanBanUsers = true
|
||||
mockAdmin.underlyingIsAccountOwner = true
|
||||
}
|
||||
let ownUserID = isAdmin ? mockAdmin.userID : RoomMemberProxyMock.mockMe.userID
|
||||
|
||||
var members: [RoomMemberProxyMock] = [
|
||||
.mockAlice,
|
||||
@@ -160,7 +157,10 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview {
|
||||
}
|
||||
|
||||
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(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
appSettings: ServiceLocator.shared.settings)
|
||||
|
||||
@@ -589,7 +589,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
guard
|
||||
let members = await roomProxy.members(),
|
||||
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 {
|
||||
userIndicatorController.alertInfo = .init(id: .init(), title: L10n.commonError)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user