Various tweaks (#1129)
* Fixes #1121 - Hide the loading indicator after the logout task finishes * Manually restart the sync only when entering the `error` state * Use stopSync instead of the roomListService directly on client deinit * Replace WeakClientProxyWrapper with callback based delegate * Fix homescreen user avatar not automatically updating * Replace default Build SDK profile with reldbg, which is fast but also doesn't crash * Always show the loading indicator when the room list is not in a `running` state * Implement delayed user indicator presentations through the normal API * Fix the unit tests * Replace UserIndicatorController delayedIndicators dictionary with a plain set
This commit is contained in:
@@ -325,7 +325,6 @@
|
||||
804C15D8ADE0EA7A5268F58A /* OverridableAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648DD1C10E4957CB791FE0B8 /* OverridableAvatarImage.swift */; };
|
||||
80D00A7C62AAB44F54725C43 /* PermalinkBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754E66A8970963B15B2A41E /* PermalinkBuilder.swift */; };
|
||||
80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */; };
|
||||
8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */; };
|
||||
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36C0A6D59717193F49EA986 /* UserSessionTests.swift */; };
|
||||
8285FF4B2C2331758C437FF7 /* ReportContentScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 713B48DBF65DE4B0DD445D66 /* ReportContentScreenViewModelProtocol.swift */; };
|
||||
828EA5009557C2B9DCD4CA0F /* UserDiscoverySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */; };
|
||||
@@ -426,6 +425,7 @@
|
||||
A14A9419105A1CD42F0511C4 /* UserIndicatorModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */; };
|
||||
A17FAD2EBC53E17B5FD384DB /* InviteUsersScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22730A30C50AC2E3D5BA8642 /* InviteUsersScreenViewModelProtocol.swift */; };
|
||||
A1D4033881320C9EB88196E6 /* ServerConfirmationScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE846DDA83BFD7EC5C03760B /* ServerConfirmationScreenUITests.swift */; };
|
||||
A1DF0E1E526A981ED6D5DF44 /* UserIndicatorControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */; };
|
||||
A216C83ADCF32BA5EF8A6FBC /* InviteUsersViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845DDBDE5A0887E73D38B826 /* InviteUsersViewModelTests.swift */; };
|
||||
A23B8B27A1436A1049EEF68E /* InfoPlistReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A580295A56B55A856CC4084 /* InfoPlistReader.swift */; };
|
||||
A2434D4DFB49A68E5CD0F53C /* MediaLoaderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A02406480C351B8C6E0682C /* MediaLoaderProtocol.swift */; };
|
||||
@@ -775,7 +775,6 @@
|
||||
0C88046D6A070D9827181C4D /* OnboardingUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingUITests.swift; sourceTree = "<group>"; };
|
||||
0D0B159AFFBBD8ECFD0E37FA /* LoginScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenModels.swift; sourceTree = "<group>"; };
|
||||
0D8F620C8B314840D8602E3F /* NSE.appex */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "wrapper.app-extension"; path = NSE.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationControllerTests.swift; sourceTree = "<group>"; };
|
||||
0E8BDC092D817B68CD9040C5 /* UserSessionStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSessionStore.swift; sourceTree = "<group>"; };
|
||||
0F19DBE940499D3E3DD405D8 /* RoomMemberDetailsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMemberDetailsScreenUITests.swift; sourceTree = "<group>"; };
|
||||
0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = "<group>"; };
|
||||
@@ -835,6 +834,7 @@
|
||||
227AC5D71A4CE43512062243 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||
23AA3F4B285570805CB0CCDD /* MapTiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTiler.swift; sourceTree = "<group>"; };
|
||||
24227FF9A2797F6EA7F69CDD /* HomeScreenInvitesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenInvitesButton.swift; sourceTree = "<group>"; };
|
||||
2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerTests.swift; sourceTree = "<group>"; };
|
||||
248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionVerificationControllerProxyMock.swift; sourceTree = "<group>"; };
|
||||
24DEE0682C95F897B6C7CB0D /* ServerConfirmationScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConfirmationScreenViewModel.swift; sourceTree = "<group>"; };
|
||||
24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenViewModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@@ -2363,7 +2363,7 @@
|
||||
2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */,
|
||||
1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */,
|
||||
EB3B237387B8288A5A938F1B /* UserAgentBuilderTests.swift */,
|
||||
0DE6C5C756E1393202BA95CD /* UserNotificationControllerTests.swift */,
|
||||
2429224EB0EEA34D35CE9249 /* UserIndicatorControllerTests.swift */,
|
||||
BA241DEEF7C8A7181C0AEDC9 /* UserPreferenceTests.swift */,
|
||||
53280D2292E6C9C7821773FD /* UserSession */,
|
||||
70C5B842301AC281DF374E41 /* Extensions */,
|
||||
@@ -3874,8 +3874,8 @@
|
||||
AF33B9044498211C3D82F1E1 /* UNTextInputNotificationResponse+Creator.swift in Sources */,
|
||||
8D3E1FADD78E72504DE0E402 /* UserAgentBuilderTests.swift in Sources */,
|
||||
E313BDD2B8813144139B2E00 /* UserDiscoveryServiceTest.swift in Sources */,
|
||||
A1DF0E1E526A981ED6D5DF44 /* UserIndicatorControllerTests.swift in Sources */,
|
||||
08248D02BACA75CDC3B39A96 /* UserNotificationCenterSpy.swift in Sources */,
|
||||
8196A2E71ACC902DD69F24EE /* UserNotificationControllerTests.swift in Sources */,
|
||||
04F17DE71A50206336749BAC /* UserPreferenceTests.swift in Sources */,
|
||||
81A7C020CB5F6232242A8414 /* UserSessionTests.swift in Sources */,
|
||||
99F8DA4CCC6772EE5FE68E24 /* ViewModelContext.swift in Sources */,
|
||||
|
||||
@@ -52,8 +52,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
private var appDelegateObserver: AnyCancellable?
|
||||
private var userSessionObserver: AnyCancellable?
|
||||
private var clientProxyObserver: AnyCancellable?
|
||||
private var networkMonitorObserver: AnyCancellable?
|
||||
private var initialSyncObserver: AnyCancellable?
|
||||
private var backgroundRefreshSyncObserver: AnyCancellable?
|
||||
|
||||
let notificationManager: NotificationManagerProtocol
|
||||
@@ -355,15 +355,12 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
showLoadingIndicator()
|
||||
|
||||
defer {
|
||||
hideLoadingIndicator()
|
||||
}
|
||||
|
||||
stopSync()
|
||||
userSessionFlowCoordinator?.stop()
|
||||
|
||||
guard !isSoft else {
|
||||
stateMachine.processEvent(.completedSigningOut(isSoft: isSoft))
|
||||
hideLoadingIndicator()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -380,6 +377,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
ServiceLocator.shared.analytics.resetConsentState()
|
||||
|
||||
stateMachine.processEvent(.completedSigningOut(isSoft: isSoft))
|
||||
|
||||
hideLoadingIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,6 +518,8 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
backgroundAppRefreshTask?.setTaskCompleted(success: true)
|
||||
backgroundAppRefreshTask = nil
|
||||
|
||||
clientProxyObserver = nil
|
||||
}
|
||||
|
||||
private func startSync() {
|
||||
@@ -532,15 +533,18 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate,
|
||||
|
||||
let identifier = "StaleDataIndicator"
|
||||
|
||||
ServiceLocator.shared.userIndicatorController.submitIndicator(.init(id: identifier, type: .toast(progress: .indeterminate), title: L10n.commonSyncing, persistent: true))
|
||||
|
||||
initialSyncObserver = userSession.clientProxy
|
||||
clientProxyObserver = userSession.clientProxy
|
||||
.callbacks
|
||||
.receive(on: DispatchQueue.main)
|
||||
.filter(\.isSyncUpdate)
|
||||
.sink { [weak self] _ in
|
||||
ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(identifier)
|
||||
self?.initialSyncObserver?.cancel()
|
||||
.sink { action in
|
||||
switch action {
|
||||
case .startedUpdating:
|
||||
ServiceLocator.shared.userIndicatorController.submitIndicator(.init(id: identifier, type: .toast(progress: .indeterminate), title: L10n.commonSyncing, persistent: true))
|
||||
case .receivedSyncUpdate:
|
||||
ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(identifier)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1210,19 +1210,19 @@ class UserIndicatorControllerMock: UserIndicatorControllerProtocol {
|
||||
|
||||
//MARK: - submitIndicator
|
||||
|
||||
var submitIndicatorCallsCount = 0
|
||||
var submitIndicatorCalled: Bool {
|
||||
return submitIndicatorCallsCount > 0
|
||||
var submitIndicatorDelayCallsCount = 0
|
||||
var submitIndicatorDelayCalled: Bool {
|
||||
return submitIndicatorDelayCallsCount > 0
|
||||
}
|
||||
var submitIndicatorReceivedIndicator: UserIndicator?
|
||||
var submitIndicatorReceivedInvocations: [UserIndicator] = []
|
||||
var submitIndicatorClosure: ((UserIndicator) -> Void)?
|
||||
var submitIndicatorDelayReceivedArguments: (indicator: UserIndicator, delay: Duration?)?
|
||||
var submitIndicatorDelayReceivedInvocations: [(indicator: UserIndicator, delay: Duration?)] = []
|
||||
var submitIndicatorDelayClosure: ((UserIndicator, Duration?) -> Void)?
|
||||
|
||||
func submitIndicator(_ indicator: UserIndicator) {
|
||||
submitIndicatorCallsCount += 1
|
||||
submitIndicatorReceivedIndicator = indicator
|
||||
submitIndicatorReceivedInvocations.append(indicator)
|
||||
submitIndicatorClosure?(indicator)
|
||||
func submitIndicator(_ indicator: UserIndicator, delay: Duration?) {
|
||||
submitIndicatorDelayCallsCount += 1
|
||||
submitIndicatorDelayReceivedArguments = (indicator: indicator, delay: delay)
|
||||
submitIndicatorDelayReceivedInvocations.append((indicator: indicator, delay: delay))
|
||||
submitIndicatorDelayClosure?(indicator, delay)
|
||||
}
|
||||
//MARK: - retractIndicatorWithId
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import Foundation
|
||||
extension UserIndicatorControllerMock {
|
||||
static var `default`: UserIndicatorControllerMock {
|
||||
let mock = UserIndicatorControllerMock()
|
||||
mock.submitIndicatorClosure = { _ in }
|
||||
mock.submitIndicatorDelayClosure = { _, _ in }
|
||||
mock.retractIndicatorWithIdClosure = { _ in }
|
||||
mock.retractAllIndicatorsClosure = { }
|
||||
return mock
|
||||
|
||||
@@ -21,6 +21,7 @@ class UserIndicatorController: ObservableObject, UserIndicatorControllerProtocol
|
||||
|
||||
private var dismisalTimer: Timer?
|
||||
private var displayTimes = [String: Date]()
|
||||
private var delayedIndicators = Set<String>()
|
||||
|
||||
var nonPersistentDisplayDuration = 2.5
|
||||
var minimumDisplayDuration = 0.5
|
||||
@@ -51,12 +52,27 @@ class UserIndicatorController: ObservableObject, UserIndicatorControllerProtocol
|
||||
)
|
||||
}
|
||||
|
||||
func submitIndicator(_ indicator: UserIndicator) {
|
||||
func submitIndicator(_ indicator: UserIndicator, delay: Duration?) {
|
||||
if let index = indicatorQueue.firstIndex(where: { $0.id == indicator.id }) {
|
||||
indicatorQueue[index] = indicator
|
||||
} else {
|
||||
retractIndicatorWithId(indicator.id)
|
||||
indicatorQueue.append(indicator)
|
||||
if let delay {
|
||||
delayedIndicators.insert(indicator.id)
|
||||
Timer.scheduledTimer(withTimeInterval: Double(delay.components.seconds), repeats: false) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
guard delayedIndicators.contains(indicator.id) else {
|
||||
return
|
||||
}
|
||||
|
||||
retractIndicatorWithId(indicator.id)
|
||||
indicatorQueue.append(indicator)
|
||||
delayedIndicators.remove(indicator.id)
|
||||
}
|
||||
} else {
|
||||
retractIndicatorWithId(indicator.id)
|
||||
indicatorQueue.append(indicator)
|
||||
}
|
||||
}
|
||||
|
||||
displayTimes[indicator.id] = .now
|
||||
@@ -69,6 +85,8 @@ class UserIndicatorController: ObservableObject, UserIndicatorControllerProtocol
|
||||
}
|
||||
|
||||
func retractIndicatorWithId(_ id: String) {
|
||||
delayedIndicators.remove(id)
|
||||
|
||||
guard let displayTime = displayTimes[id], abs(displayTime.timeIntervalSinceNow) <= minimumDisplayDuration else {
|
||||
indicatorQueue.removeAll { $0.id == id }
|
||||
return
|
||||
|
||||
@@ -18,19 +18,14 @@ import Foundation
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol UserIndicatorControllerProtocol: CoordinatorProtocol {
|
||||
func submitIndicator(_ indicator: UserIndicator)
|
||||
func submitIndicator(_ indicator: UserIndicator, delay: Duration?)
|
||||
func retractIndicatorWithId(_ id: String)
|
||||
func retractAllIndicators()
|
||||
var alertInfo: AlertInfo<UUID>? { get set }
|
||||
}
|
||||
|
||||
extension UserIndicatorControllerProtocol {
|
||||
/// Allows to submit a delayed indicator, this returns a Task so that it's also possible to cancel the action
|
||||
func submitIndicator(_ indicator: UserIndicator, delay: Duration) -> Task<Void, Never> {
|
||||
Task { @MainActor in
|
||||
try? await Task.sleep(for: delay)
|
||||
guard !Task.isCancelled else { return }
|
||||
submitIndicator(indicator)
|
||||
}
|
||||
func submitIndicator(_ indicator: UserIndicator) {
|
||||
submitIndicator(indicator, delay: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import SwiftUI
|
||||
struct HomeScreenUserMenuButton: View {
|
||||
@State private var showingLogoutConfirmation = false
|
||||
|
||||
let context: HomeScreenViewModel.Context
|
||||
@ObservedObject var context: HomeScreenViewModel.Context
|
||||
|
||||
var body: some View {
|
||||
Menu {
|
||||
|
||||
@@ -26,7 +26,6 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
|
||||
private let roomType: InviteUsersScreenRoomType
|
||||
private weak var userIndicatorController: UserIndicatorControllerProtocol?
|
||||
private let actionsSubject: PassthroughSubject<InviteUsersScreenViewModelAction, Never> = .init()
|
||||
@CancellableTask private var showLoaderTask: Task<Void, Never>?
|
||||
|
||||
var actions: AnyPublisher<InviteUsersScreenViewModelAction, Never> {
|
||||
actionsSubject.eraseToAnyPublisher()
|
||||
@@ -165,11 +164,10 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
|
||||
private let userIndicatorID = UUID().uuidString
|
||||
|
||||
private func showLoader() {
|
||||
showLoaderTask = userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID, type: .modal, title: L10n.commonLoading, persistent: true), delay: .milliseconds(200))
|
||||
userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID, type: .modal, title: L10n.commonLoading, persistent: true), delay: .milliseconds(200))
|
||||
}
|
||||
|
||||
private func hideLoader() {
|
||||
showLoaderTask = nil
|
||||
userIndicatorController?.retractIndicatorWithId(userIndicatorID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ typealias RoomMembersListScreenViewModelType = StateStoreViewModel<RoomMembersLi
|
||||
class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMembersListScreenViewModelProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private var members: [RoomMemberProxyProtocol] = []
|
||||
@CancellableTask private var showLoaderTask: Task<Void, Never>?
|
||||
|
||||
var callback: ((RoomMembersListScreenViewModelAction) -> Void)?
|
||||
|
||||
@@ -109,11 +108,10 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe
|
||||
private let userIndicatorID = UUID().uuidString
|
||||
|
||||
private func showLoader() {
|
||||
showLoaderTask = ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID, type: .modal, title: L10n.commonLoading, persistent: true), delay: .milliseconds(200))
|
||||
ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: userIndicatorID, type: .modal, title: L10n.commonLoading, persistent: true), delay: .milliseconds(200))
|
||||
}
|
||||
|
||||
private func hideLoader() {
|
||||
showLoaderTask = nil
|
||||
ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(userIndicatorID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let timelineController: RoomTimelineControllerProtocol
|
||||
private unowned let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private var loadingTask: Task<Void, Never>?
|
||||
|
||||
init(timelineController: RoomTimelineControllerProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
@@ -512,9 +511,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
private func handleTappedUser(userID: String) async {
|
||||
// This is generally fast but it could take some time for rooms with thousands of users on first load
|
||||
// Show a loader only if it takes more than 0.1 seconds
|
||||
loadingTask = showLoadingIndicator(with: .milliseconds(100))
|
||||
showLoadingIndicator(with: .milliseconds(100))
|
||||
let result = await roomProxy.getMember(userID: userID)
|
||||
loadingTask?.cancel()
|
||||
hideLoadingIndicator()
|
||||
|
||||
switch result {
|
||||
@@ -544,7 +542,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
private static let loadingIndicatorIdentifier = "RoomScreenLoadingIndicator"
|
||||
|
||||
private func showLoadingIndicator(with delay: Duration) -> Task<Void, Never> {
|
||||
private func showLoadingIndicator(with delay: Duration) {
|
||||
userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
|
||||
type: .modal(progress: .indeterminate, interactiveDismissDisabled: true),
|
||||
title: L10n.commonLoading,
|
||||
|
||||
@@ -19,26 +19,6 @@ import Foundation
|
||||
import MatrixRustSDK
|
||||
import UIKit
|
||||
|
||||
private class WeakClientProxyWrapper: ClientDelegate {
|
||||
private weak var clientProxy: ClientProxy?
|
||||
|
||||
init(clientProxy: ClientProxy) {
|
||||
self.clientProxy = clientProxy
|
||||
}
|
||||
|
||||
// MARK: - ClientDelegate
|
||||
|
||||
func didReceiveAuthError(isSoftLogout: Bool) {
|
||||
MXLog.error("Received authentication error, softlogout=\(isSoftLogout)")
|
||||
clientProxy?.didReceiveAuthError(isSoftLogout: isSoftLogout)
|
||||
}
|
||||
|
||||
func didRefreshTokens() {
|
||||
MXLog.info("The session has updated tokens.")
|
||||
clientProxy?.updateRestorationToken()
|
||||
}
|
||||
}
|
||||
|
||||
class ClientProxy: ClientProxyProtocol {
|
||||
private let client: ClientProtocol
|
||||
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
||||
@@ -67,10 +47,8 @@ class ClientProxy: ClientProxyProtocol {
|
||||
private var visibleRoomsListProxyStateObservationToken: AnyCancellable?
|
||||
|
||||
deinit {
|
||||
// These need to be inlined instead of using stopSync()
|
||||
// as we can't call async methods safely from deinit
|
||||
client.setDelegate(delegate: nil)
|
||||
try? roomListService?.stopSync()
|
||||
stopSync()
|
||||
}
|
||||
|
||||
let callbacks = PassthroughSubject<ClientProxyCallback, Never>()
|
||||
@@ -82,8 +60,11 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
mediaLoader = MediaLoader(client: client, clientQueue: clientQueue)
|
||||
|
||||
let delegate = WeakClientProxyWrapper(clientProxy: self)
|
||||
client.setDelegate(delegate: delegate)
|
||||
client.setDelegate(delegate: ClientDelegateWrapper { [weak self] isSoftLogout in
|
||||
self?.callbacks.send(.receivedAuthError(isSoftLogout: isSoftLogout))
|
||||
} tokenRefreshCallback: { [weak self] in
|
||||
self?.callbacks.send(.updateRestorationToken)
|
||||
})
|
||||
|
||||
await configureRoomListService()
|
||||
|
||||
@@ -391,19 +372,25 @@ class ClientProxy: ClientProxyProtocol {
|
||||
MXLog.info("Received room list update: \(state)")
|
||||
|
||||
// Restart the room list sync on every error for now
|
||||
if state == .terminated {
|
||||
if state == .error {
|
||||
self.restartSync()
|
||||
}
|
||||
|
||||
// The invites are available only when entering `running`
|
||||
if state == .running {
|
||||
self.callbacks.send(.receivedSyncUpdate)
|
||||
|
||||
Task {
|
||||
// Subscribe to invites later as the underlying SlidingSync list is only added when entering AllRooms
|
||||
await self.inviteSummaryProvider?.subscribeIfNecessary(entriesFunction: roomListService.invites(listener:),
|
||||
entriesLoadingStateFunction: nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Anything that's not `running` is interpreted as "Loading data"
|
||||
if state == .running {
|
||||
self.callbacks.send(.receivedSyncUpdate)
|
||||
} else {
|
||||
self.callbacks.send(.startedUpdating)
|
||||
}
|
||||
})
|
||||
|
||||
roomSummaryProvider = RoomSummaryProvider(roomListService: roomListService,
|
||||
@@ -434,14 +421,6 @@ class ClientProxy: ClientProxyProtocol {
|
||||
return (nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func updateRestorationToken() {
|
||||
callbacks.send(.updateRestorationToken)
|
||||
}
|
||||
|
||||
fileprivate func didReceiveAuthError(isSoftLogout: Bool) {
|
||||
callbacks.send(.receivedAuthError(isSoftLogout: isSoftLogout))
|
||||
}
|
||||
}
|
||||
|
||||
extension ClientProxy: MediaLoaderProtocol {
|
||||
@@ -469,3 +448,26 @@ private class RoomListStateListenerProxy: RoomListStateListener {
|
||||
onUpdateClosure(state)
|
||||
}
|
||||
}
|
||||
|
||||
private class ClientDelegateWrapper: ClientDelegate {
|
||||
private let authErrorCallback: (Bool) -> Void
|
||||
private let tokenRefreshCallback: () -> Void
|
||||
|
||||
init(authErrorCallback: @escaping (Bool) -> Void,
|
||||
tokenRefreshCallback: @escaping () -> Void) {
|
||||
self.authErrorCallback = authErrorCallback
|
||||
self.tokenRefreshCallback = tokenRefreshCallback
|
||||
}
|
||||
|
||||
// MARK: - ClientDelegate
|
||||
|
||||
func didReceiveAuthError(isSoftLogout: Bool) {
|
||||
MXLog.error("Received authentication error, softlogout=\(isSoftLogout)")
|
||||
authErrorCallback(isSoftLogout)
|
||||
}
|
||||
|
||||
func didRefreshTokens() {
|
||||
MXLog.info("The session has updated tokens.")
|
||||
tokenRefreshCallback()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
enum ClientProxyCallback {
|
||||
case startedUpdating
|
||||
case receivedSyncUpdate
|
||||
case receivedAuthError(isSoftLogout: Bool)
|
||||
case updateRestorationToken
|
||||
|
||||
@@ -25,7 +25,7 @@ struct BuildSDK: ParsableCommand {
|
||||
var target: Target?
|
||||
|
||||
@Option(help: "The profile to use when building the SDK. Omit this option to build in debug mode.")
|
||||
var profile: Profile = .debug
|
||||
var profile: Profile = .reldbg
|
||||
|
||||
enum Error: LocalizedError {
|
||||
case rustupOutputFailure
|
||||
|
||||
@@ -185,7 +185,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
// Test
|
||||
viewModel.context.send(viewAction: .tappedOnUser(userID: "bob"))
|
||||
await Task.yield()
|
||||
XCTAssertFalse(userIndicatorControllerMock.submitIndicatorCalled)
|
||||
XCTAssertFalse(userIndicatorControllerMock.submitIndicatorDelayCalled)
|
||||
XCTAssert(roomProxyMock.getMemberUserIDCallsCount == 1)
|
||||
XCTAssertEqual(roomProxyMock.getMemberUserIDReceivedUserID, "bob")
|
||||
}
|
||||
@@ -217,7 +217,7 @@ class RoomScreenViewModelTests: XCTestCase {
|
||||
// Test
|
||||
viewModel.context.send(viewAction: .tappedOnUser(userID: "bob"))
|
||||
try? await Task.sleep(for: .milliseconds(300))
|
||||
XCTAssert(userIndicatorControllerMock.submitIndicatorCallsCount == 1)
|
||||
XCTAssert(userIndicatorControllerMock.submitIndicatorDelayCallsCount == 1)
|
||||
XCTAssert(userIndicatorControllerMock.retractIndicatorWithIdCallsCount == 1)
|
||||
XCTAssert(roomProxyMock.getMemberUserIDCallsCount == 1)
|
||||
XCTAssertEqual(roomProxyMock.getMemberUserIDReceivedUserID, "bob")
|
||||
|
||||
Reference in New Issue
Block a user