mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Refactor SecureBackupControllerListener into SDKListener and use it everywhere. (#4030)
This commit is contained in:
@@ -2002,8 +2002,8 @@ class AuthenticationClientBuilderMock: AuthenticationClientBuilderProtocol, @unc
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerCalled: Bool {
|
||||
return buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerCallsCount > 0
|
||||
}
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerReceivedArguments: (qrCodeData: QrCodeData, oidcConfiguration: OIDCConfigurationProxy, progressListener: QrLoginProgressListenerProxy)?
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerReceivedInvocations: [(qrCodeData: QrCodeData, oidcConfiguration: OIDCConfigurationProxy, progressListener: QrLoginProgressListenerProxy)] = []
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerReceivedArguments: (qrCodeData: QrCodeData, oidcConfiguration: OIDCConfigurationProxy, progressListener: SDKListener<QrLoginProgress>)?
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerReceivedInvocations: [(qrCodeData: QrCodeData, oidcConfiguration: OIDCConfigurationProxy, progressListener: SDKListener<QrLoginProgress>)] = []
|
||||
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerUnderlyingReturnValue: ClientProtocol!
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerReturnValue: ClientProtocol! {
|
||||
@@ -2029,9 +2029,9 @@ class AuthenticationClientBuilderMock: AuthenticationClientBuilderProtocol, @unc
|
||||
}
|
||||
}
|
||||
}
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerClosure: ((QrCodeData, OIDCConfigurationProxy, QrLoginProgressListenerProxy) async throws -> ClientProtocol)?
|
||||
var buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerClosure: ((QrCodeData, OIDCConfigurationProxy, SDKListener<QrLoginProgress>) async throws -> ClientProtocol)?
|
||||
|
||||
func buildWithQRCode(qrCodeData: QrCodeData, oidcConfiguration: OIDCConfigurationProxy, progressListener: QrLoginProgressListenerProxy) async throws -> ClientProtocol {
|
||||
func buildWithQRCode(qrCodeData: QrCodeData, oidcConfiguration: OIDCConfigurationProxy, progressListener: SDKListener<QrLoginProgress>) async throws -> ClientProtocol {
|
||||
if let error = buildWithQRCodeQrCodeDataOidcConfigurationProgressListenerThrowableError {
|
||||
throw error
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
/// A helper class that can be passed as this listener for SDK callbacks.
|
||||
///
|
||||
/// To use this you'll need to add a conformance to the required listener
|
||||
/// protocol with a specialisation for the type it listens for.
|
||||
final class SDKListener<T> {
|
||||
private let onUpdateClosure: (T) -> Void
|
||||
|
||||
/// Creates a new listener.
|
||||
/// - Parameter onUpdateClosure: A closure that will be called whenever a new value is available.
|
||||
init(_ onUpdateClosure: @escaping (T) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: QRCodeLoginService
|
||||
|
||||
extension SDKListener: QrLoginProgressListener where T == QrLoginProgress {
|
||||
func onUpdate(state: QrLoginProgress) { onUpdateClosure(state) }
|
||||
}
|
||||
|
||||
// MARK: ClientProxy
|
||||
|
||||
extension SDKListener: SyncServiceStateObserver where T == SyncServiceState {
|
||||
func onUpdate(state: SyncServiceState) { onUpdateClosure(state) }
|
||||
}
|
||||
|
||||
extension SDKListener: RoomListServiceStateListener where T == RoomListServiceState {
|
||||
func onUpdate(state: RoomListServiceState) { onUpdateClosure(state) }
|
||||
}
|
||||
|
||||
extension SDKListener: RoomListServiceSyncIndicatorListener where T == RoomListServiceSyncIndicator {
|
||||
func onUpdate(syncIndicator: RoomListServiceSyncIndicator) { onUpdateClosure(syncIndicator) }
|
||||
}
|
||||
|
||||
extension SDKListener: VerificationStateListener where T == VerificationState {
|
||||
func onUpdate(status: VerificationState) { onUpdateClosure(status) }
|
||||
}
|
||||
|
||||
// MARK: SecureBackupController
|
||||
|
||||
extension SDKListener: BackupStateListener where T == BackupState {
|
||||
func onUpdate(status: BackupState) { onUpdateClosure(status) }
|
||||
}
|
||||
|
||||
extension SDKListener: RecoveryStateListener where T == RecoveryState {
|
||||
func onUpdate(status: RecoveryState) { onUpdateClosure(status) }
|
||||
}
|
||||
|
||||
extension SDKListener: EnableRecoveryProgressListener where T == EnableRecoveryProgress {
|
||||
func onUpdate(status: EnableRecoveryProgress) { onUpdateClosure(status) }
|
||||
}
|
||||
|
||||
extension SDKListener: BackupSteadyStateListener where T == BackupUploadState {
|
||||
func onUpdate(status: BackupUploadState) { onUpdateClosure(status) }
|
||||
}
|
||||
|
||||
// MARK: RoomSummaryProvider
|
||||
|
||||
extension SDKListener: RoomListEntriesListener where T == [RoomListEntriesUpdate] {
|
||||
func onUpdate(roomEntriesUpdate: [RoomListEntriesUpdate]) { onUpdateClosure(roomEntriesUpdate) }
|
||||
}
|
||||
|
||||
extension SDKListener: RoomListLoadingStateListener where T == RoomListLoadingState {
|
||||
func onUpdate(state: RoomListLoadingState) { onUpdateClosure(state) }
|
||||
}
|
||||
|
||||
// MARK: TimelineProxy
|
||||
|
||||
extension SDKListener: PaginationStatusListener where T == RoomPaginationStatus {
|
||||
func onUpdate(status: RoomPaginationStatus) { onUpdateClosure(status) }
|
||||
}
|
||||
|
||||
extension SDKListener: ProgressWatcher where T == Double {
|
||||
func transmissionProgress(progress: TransmissionProgress) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.onUpdateClosure(Double(progress.current) / Double(progress.total))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: TimelineProvider
|
||||
|
||||
extension SDKListener: TimelineListener where T == [TimelineDiff] {
|
||||
func onUpdate(diff: [TimelineDiff]) { onUpdateClosure(diff) }
|
||||
}
|
||||
|
||||
// MARK: RoomDirectorySearchProxy
|
||||
|
||||
extension SDKListener: RoomDirectorySearchEntriesListener where T == [RoomDirectorySearchEntryUpdate] {
|
||||
func onUpdate(roomEntriesUpdate: [RoomDirectorySearchEntryUpdate]) { onUpdateClosure(roomEntriesUpdate) }
|
||||
}
|
||||
@@ -13,7 +13,7 @@ protocol AuthenticationClientBuilderProtocol {
|
||||
func build(homeserverAddress: String) async throws -> ClientProtocol
|
||||
func buildWithQRCode(qrCodeData: QrCodeData,
|
||||
oidcConfiguration: OIDCConfigurationProxy,
|
||||
progressListener: QrLoginProgressListenerProxy) async throws -> ClientProtocol
|
||||
progressListener: SDKListener<QrLoginProgress>) async throws -> ClientProtocol
|
||||
}
|
||||
|
||||
/// A wrapper around `ClientBuilder` to share reusable code between Normal and QR logins.
|
||||
@@ -33,7 +33,7 @@ struct AuthenticationClientBuilder: AuthenticationClientBuilderProtocol {
|
||||
/// Builds a Client, authenticating with the given QR code data.
|
||||
func buildWithQRCode(qrCodeData: QrCodeData,
|
||||
oidcConfiguration: OIDCConfigurationProxy,
|
||||
progressListener: QrLoginProgressListenerProxy) async throws -> ClientProtocol {
|
||||
progressListener: SDKListener<QrLoginProgress>) async throws -> ClientProtocol {
|
||||
try await makeClientBuilder().buildWithQrCode(qrCodeData: qrCodeData,
|
||||
oidcConfiguration: oidcConfiguration.rustValue,
|
||||
progressListener: progressListener)
|
||||
|
||||
@@ -192,7 +192,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
|
||||
await updateVerificationState(client.encryption().verificationState())
|
||||
|
||||
verificationStateListenerTaskHandle = client.encryption().verificationStateListener(listener: VerificationStateListenerProxy { [weak self] verificationState in
|
||||
verificationStateListenerTaskHandle = client.encryption().verificationStateListener(listener: SDKListener { [weak self] verificationState in
|
||||
Task { await self?.updateVerificationState(verificationState) }
|
||||
})
|
||||
|
||||
@@ -838,7 +838,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
private func createSyncServiceStateObserver(_ syncService: SyncService) -> TaskHandle {
|
||||
syncService.state(listener: SyncServiceStateObserverProxy { [weak self] state in
|
||||
syncService.state(listener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
MXLog.info("Received sync service update: \(state)")
|
||||
@@ -856,7 +856,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
private func createRoomListServiceObserver(_ roomListService: RoomListService) -> TaskHandle {
|
||||
roomListService.state(listener: RoomListStateListenerProxy { [weak self] state in
|
||||
roomListService.state(listener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
MXLog.info("Received room list update: \(state)")
|
||||
@@ -877,7 +877,7 @@ class ClientProxy: ClientProxyProtocol {
|
||||
}
|
||||
|
||||
private func createRoomListLoadingStateUpdateObserver(_ roomListService: RoomListService) -> TaskHandle {
|
||||
roomListService.syncIndicator(delayBeforeShowingInMs: 1000, delayBeforeHidingInMs: 0, listener: RoomListServiceSyncIndicatorListenerProxy { [weak self] state in
|
||||
roomListService.syncIndicator(delayBeforeShowingInMs: 1000, delayBeforeHidingInMs: 0, listener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
switch state {
|
||||
@@ -1039,54 +1039,6 @@ extension ClientProxy: MediaLoaderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private class SyncServiceStateObserverProxy: SyncServiceStateObserver {
|
||||
private let onUpdateClosure: (SyncServiceState) -> Void
|
||||
|
||||
init(onUpdateClosure: @escaping (SyncServiceState) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(state: SyncServiceState) {
|
||||
onUpdateClosure(state)
|
||||
}
|
||||
}
|
||||
|
||||
private class RoomListStateListenerProxy: RoomListServiceStateListener {
|
||||
private let onUpdateClosure: (RoomListServiceState) -> Void
|
||||
|
||||
init(onUpdateClosure: @escaping (RoomListServiceState) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(state: RoomListServiceState) {
|
||||
onUpdateClosure(state)
|
||||
}
|
||||
}
|
||||
|
||||
private class RoomListServiceSyncIndicatorListenerProxy: RoomListServiceSyncIndicatorListener {
|
||||
private let onUpdateClosure: (RoomListServiceSyncIndicator) -> Void
|
||||
|
||||
init(onUpdateClosure: @escaping (RoomListServiceSyncIndicator) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(syncIndicator: RoomListServiceSyncIndicator) {
|
||||
onUpdateClosure(syncIndicator)
|
||||
}
|
||||
}
|
||||
|
||||
private class VerificationStateListenerProxy: VerificationStateListener {
|
||||
private let onUpdateClosure: (VerificationState) -> Void
|
||||
|
||||
init(onUpdateClosure: @escaping (VerificationState) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(status: VerificationState) {
|
||||
onUpdateClosure(status)
|
||||
}
|
||||
}
|
||||
|
||||
private class ClientDelegateWrapper: ClientDelegate {
|
||||
private let authErrorCallback: (Bool) -> Void
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
||||
return .failure(.invalidQRCode)
|
||||
}
|
||||
|
||||
let listener = QrLoginProgressListenerProxy { [weak self] progress in
|
||||
let listener = SDKListener { [weak self] progress in
|
||||
self?.qrLoginProgressSubject.send(progress)
|
||||
}
|
||||
|
||||
@@ -92,18 +92,6 @@ final class QRCodeLoginService: QRCodeLoginServiceProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
final class QrLoginProgressListenerProxy: QrLoginProgressListener {
|
||||
private let onUpdateClosure: (QrLoginProgress) -> Void
|
||||
|
||||
init(onUpdateClosure: @escaping (QrLoginProgress) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(state: QrLoginProgress) {
|
||||
onUpdateClosure(state)
|
||||
}
|
||||
}
|
||||
|
||||
private extension HumanQrLoginError {
|
||||
var serviceError: QRCodeLoginServiceError {
|
||||
switch self {
|
||||
|
||||
@@ -89,7 +89,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
self.roomList = roomList
|
||||
|
||||
do {
|
||||
listUpdatesSubscriptionResult = roomList.entriesWithDynamicAdapters(pageSize: UInt32(roomListPageSize), listener: RoomListEntriesListenerProxy { [weak self] updates in
|
||||
listUpdatesSubscriptionResult = roomList.entriesWithDynamicAdapters(pageSize: UInt32(roomListPageSize), listener: SDKListener { [weak self] updates in
|
||||
guard let self else { return }
|
||||
diffsPublisher.send(updates)
|
||||
})
|
||||
@@ -97,7 +97,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol {
|
||||
// Forces the listener above to be called with the current state
|
||||
setFilter(.all(filters: []))
|
||||
|
||||
let stateUpdatesSubscriptionResult = try roomList.loadingState(listener: RoomListStateObserver { [weak self] state in
|
||||
let stateUpdatesSubscriptionResult = try roomList.loadingState(listener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
MXLog.info("\(name): Received state update: \(state)")
|
||||
stateSubject.send(RoomSummaryProviderState(roomListState: state))
|
||||
@@ -383,27 +383,3 @@ extension RoomSummaryProviderState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RoomListEntriesListenerProxy: RoomListEntriesListener {
|
||||
private let onUpdateClosure: ([RoomListEntriesUpdate]) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping ([RoomListEntriesUpdate]) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(roomEntriesUpdate: [RoomListEntriesUpdate]) {
|
||||
onUpdateClosure(roomEntriesUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
private class RoomListStateObserver: RoomListLoadingStateListener {
|
||||
private let onUpdateClosure: (RoomListLoadingState) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping (RoomListLoadingState) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(state: RoomListLoadingState) {
|
||||
onUpdateClosure(state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol {
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
searchEntriesSubscription = await roomDirectorySearch.results(listener: RoomDirectorySearchEntriesListenerProxy { [weak self] updates in
|
||||
searchEntriesSubscription = await roomDirectorySearch.results(listener: SDKListener { [weak self] updates in
|
||||
self?.diffsPublisher.send(updates)
|
||||
})
|
||||
}
|
||||
@@ -152,15 +152,3 @@ final class RoomDirectorySearchProxy: RoomDirectorySearchProxyProtocol {
|
||||
canBeJoined: value.joinRule == .public || (appSettings.knockingEnabled && value.joinRule == .knock))
|
||||
}
|
||||
}
|
||||
|
||||
private final class RoomDirectorySearchEntriesListenerProxy: RoomDirectorySearchEntriesListener {
|
||||
private let onUpdateClosure: ([RoomDirectorySearchEntryUpdate]) -> Void
|
||||
|
||||
func onUpdate(roomEntriesUpdate: [RoomDirectorySearchEntryUpdate]) {
|
||||
onUpdateClosure(roomEntriesUpdate)
|
||||
}
|
||||
|
||||
init(_ onUpdateClosure: @escaping (([RoomDirectorySearchEntryUpdate]) -> Void)) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
init(encryption: Encryption) {
|
||||
self.encryption = encryption
|
||||
|
||||
backupStateListenerTaskHandle = encryption.backupStateListener(listener: SecureBackupControllerListener { [weak self] state in
|
||||
backupStateListenerTaskHandle = encryption.backupStateListener(listener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
switch state {
|
||||
@@ -62,7 +62,7 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
}
|
||||
})
|
||||
|
||||
recoveryStateListenerTaskHandle = encryption.recoveryStateListener(listener: SecureBackupControllerListener { [weak self] state in
|
||||
recoveryStateListenerTaskHandle = encryption.recoveryStateListener(listener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
switch state {
|
||||
@@ -121,7 +121,7 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
MXLog.info("Enabling recovery")
|
||||
|
||||
var keyUploadErrored = false
|
||||
let recoveryKey = try await encryption.enableRecovery(waitForBackupsToUpload: false, passphrase: nil, progressListener: SecureBackupControllerListener { [weak self] state in
|
||||
let recoveryKey = try await encryption.enableRecovery(waitForBackupsToUpload: false, passphrase: nil, progressListener: SDKListener { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
switch state {
|
||||
@@ -157,7 +157,7 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
func waitForKeyBackupUpload(uploadStateSubject: CurrentValueSubject<SecureBackupSteadyState, Never>) async -> Result<Void, SecureBackupControllerError> {
|
||||
do {
|
||||
MXLog.info("Waiting for backup upload steady state")
|
||||
try await encryption.waitForBackupUploadSteadyState(progressListener: SecureBackupControllerListener { state in
|
||||
try await encryption.waitForBackupUploadSteadyState(progressListener: SDKListener { state in
|
||||
let uploadState: SecureBackupSteadyState = switch state {
|
||||
case .waiting: .waiting
|
||||
case .uploading(let backedUpCount, let totalCount): .uploading(uploadedKeyCount: Int(backedUpCount), totalKeyCount: Int(totalCount))
|
||||
@@ -210,20 +210,3 @@ class SecureBackupController: SecureBackupControllerProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SecureBackupControllerListener<T> {
|
||||
private let onUpdateClosure: (T) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping (T) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(status: T) {
|
||||
onUpdateClosure(status)
|
||||
}
|
||||
}
|
||||
|
||||
extension SecureBackupControllerListener: BackupStateListener where T == BackupState { }
|
||||
extension SecureBackupControllerListener: RecoveryStateListener where T == RecoveryState { }
|
||||
extension SecureBackupControllerListener: EnableRecoveryProgressListener where T == EnableRecoveryProgress { }
|
||||
extension SecureBackupControllerListener: BackupSteadyStateListener where T == BackupUploadState { }
|
||||
|
||||
@@ -57,7 +57,7 @@ class TimelineProvider: TimelineProviderProtocol {
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
roomTimelineObservationToken = await timeline.addListener(listener: RoomTimelineListener { [weak self] timelineDiffs in
|
||||
roomTimelineObservationToken = await timeline.addListener(listener: SDKListener { [weak self] timelineDiffs in
|
||||
self?.serialDispatchQueue.sync {
|
||||
self?.updateItemsWithDiffs(timelineDiffs)
|
||||
}
|
||||
@@ -215,18 +215,6 @@ private extension VirtualTimelineItem {
|
||||
}
|
||||
}
|
||||
|
||||
private final class RoomTimelineListener: TimelineListener {
|
||||
private let onUpdateClosure: ([TimelineDiff]) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping ([TimelineDiff]) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(diff: [TimelineDiff]) {
|
||||
onUpdateClosure(diff)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Array where Element == TimelineDiff {
|
||||
var debugDescription: String {
|
||||
"[" + map(\.debugDescription).joined(separator: ",") + "]"
|
||||
|
||||
@@ -577,7 +577,7 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
private func subscribeToPagination() async {
|
||||
switch kind {
|
||||
case .live:
|
||||
let backPaginationListener = RoomPaginationStatusListener { [weak self] status in
|
||||
let backPaginationListener = SDKListener<RoomPaginationStatus> { [weak self] status in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@@ -610,32 +610,6 @@ final class TimelineProxy: TimelineProxyProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private final class RoomPaginationStatusListener: PaginationStatusListener {
|
||||
private let onUpdateClosure: (RoomPaginationStatus) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping (RoomPaginationStatus) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func onUpdate(status: RoomPaginationStatus) {
|
||||
onUpdateClosure(status)
|
||||
}
|
||||
}
|
||||
|
||||
private final class UploadProgressListener: ProgressWatcher {
|
||||
private let onUpdateClosure: (Double) -> Void
|
||||
|
||||
init(_ onUpdateClosure: @escaping (Double) -> Void) {
|
||||
self.onUpdateClosure = onUpdateClosure
|
||||
}
|
||||
|
||||
func transmissionProgress(progress: TransmissionProgress) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.onUpdateClosure(Double(progress.current) / Double(progress.total))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension MatrixRustSDK.PollKind {
|
||||
init(pollKind: Poll.Kind) {
|
||||
switch pollKind {
|
||||
|
||||
Reference in New Issue
Block a user