From 6ea26dd6c4169be3a8d07ec8c61b2170434e6827 Mon Sep 17 00:00:00 2001 From: Marco Romano Date: Wed, 29 Nov 2023 10:34:51 +0100 Subject: [PATCH] Upgrade to rust sdk 0.1.71 (#1905) https://github.com/matrix-org/matrix-rust-components-kotlin/releases/tag/sdk-v0.1.71 There are breaking changes as specified in: https://github.com/vector-im/element-x-android/issues/1898 plus the one related to the poll history feature. --- .../features/logout/impl/LogoutView.kt | 3 +- .../impl/setup/SecureBackupSetupPresenter.kt | 8 +-- gradle/libs.versions.toml | 2 +- .../api/encryption/BackupUploadState.kt | 5 -- .../api/encryption/EnableRecoveryProgress.kt | 5 +- .../libraries/matrix/api/room/MatrixRoom.kt | 2 + .../matrix/api/timeline/MatrixTimeline.kt | 2 +- .../libraries/matrix/impl/RustMatrixClient.kt | 1 + .../encryption/BackupUploadStateMapper.kt | 5 -- .../EnableRecoveryProgressMapper.kt | 4 +- .../impl/encryption/RustEncryptionService.kt | 4 +- .../encryption/SteadyStateExceptionMapper.kt | 2 +- .../matrix/impl/room/RoomContentForwarder.kt | 14 ++--- .../matrix/impl/room/RustMatrixRoom.kt | 61 +++++++++++-------- .../impl/timeline/RoomTimelineExtensions.kt | 19 +++--- .../impl/timeline/RustMatrixTimeline.kt | 22 ++++--- .../test/encryption/FakeEncryptionService.kt | 2 +- .../matrix/test/room/FakeMatrixRoom.kt | 3 + .../test/timeline/FakeMatrixTimeline.kt | 2 + 19 files changed, 91 insertions(+), 75 deletions(-) diff --git a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt index 65b6e91682..fd559642a5 100644 --- a/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt +++ b/features/logout/impl/src/main/kotlin/io/element/android/features/logout/impl/LogoutView.kt @@ -140,8 +140,7 @@ private fun BackupUploadState.isBackingUp(): Boolean { return when (this) { BackupUploadState.Unknown, BackupUploadState.Waiting, - is BackupUploadState.Uploading, - is BackupUploadState.CheckingIfUploadNeeded -> true + is BackupUploadState.Uploading -> true is BackupUploadState.SteadyException -> exception is SteadyStateException.Connection BackupUploadState.Done, BackupUploadState.Error -> false diff --git a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt index 1bba716bb1..eab2e0450d 100644 --- a/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt +++ b/features/securebackup/impl/src/main/kotlin/io/element/android/features/securebackup/impl/setup/SecureBackupSetupPresenter.kt @@ -129,11 +129,11 @@ class SecureBackupSetupPresenter @AssistedInject constructor( encryptionService.enableRecoveryProgressStateFlow.collect { enableRecoveryProgress -> Timber.tag(loggerTagSetup.value).d("New enableRecoveryProgress: ${enableRecoveryProgress.javaClass.simpleName}") when (enableRecoveryProgress) { - EnableRecoveryProgress.Unknown, + is EnableRecoveryProgress.Starting, + is EnableRecoveryProgress.CreatingBackup, + is EnableRecoveryProgress.CreatingRecoveryKey, is EnableRecoveryProgress.BackingUp, - EnableRecoveryProgress.CreatingBackup, - EnableRecoveryProgress.CreatingRecoveryKey -> - Unit + is EnableRecoveryProgress.RoomKeyUploadError -> Unit is EnableRecoveryProgress.Done -> stateAndDispatch.dispatchAction(SecureBackupSetupStateMachine.Event.SdkHasCreatedKey(enableRecoveryProgress.recoveryKey)) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 497a96031d..4517c809a3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -147,7 +147,7 @@ jsoup = "org.jsoup:jsoup:1.17.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:1.3.1" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.70" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.1.71" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupUploadState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupUploadState.kt index 8b5d721b28..61130c43db 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupUploadState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/BackupUploadState.kt @@ -19,11 +19,6 @@ package io.element.android.libraries.matrix.api.encryption sealed interface BackupUploadState { data object Unknown : BackupUploadState - data class CheckingIfUploadNeeded( - val backedUpCount: Int, - val totalCount: Int, - ) : BackupUploadState - data object Waiting : BackupUploadState data class Uploading( diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EnableRecoveryProgress.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EnableRecoveryProgress.kt index 1ee85a1cc1..ed45293c49 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EnableRecoveryProgress.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/encryption/EnableRecoveryProgress.kt @@ -17,9 +17,10 @@ package io.element.android.libraries.matrix.api.encryption sealed interface EnableRecoveryProgress { - data object Unknown : EnableRecoveryProgress - data object CreatingRecoveryKey : EnableRecoveryProgress + data object Starting : EnableRecoveryProgress data object CreatingBackup : EnableRecoveryProgress + data object CreatingRecoveryKey : EnableRecoveryProgress data class BackingUp(val backedUpCount: Int, val totalCount: Int) : EnableRecoveryProgress + data object RoomKeyUploadError : EnableRecoveryProgress data class Done(val recoveryKey: String) : EnableRecoveryProgress } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt index 19daf7d50d..f9fbffa4a6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoom.kt @@ -238,5 +238,7 @@ interface MatrixRoom : Closeable { */ fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result + suspend fun pollHistory(): MatrixTimeline + override fun close() = destroy() } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimeline.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimeline.kt index 5fa55c357f..8dfa2e4819 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimeline.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/MatrixTimeline.kt @@ -20,7 +20,7 @@ import io.element.android.libraries.matrix.api.core.EventId import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -interface MatrixTimeline { +interface MatrixTimeline: AutoCloseable { data class PaginationState( val isBackPaginating: Boolean, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index c277a01791..ef08f32edf 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -214,6 +214,7 @@ class RustMatrixClient constructor( isKeyBackupEnabled = client.encryption().backupState() == BackupState.ENABLED, roomListItem = roomListItem, innerRoom = fullRoom, + innerTimeline = fullRoom.timeline(), roomNotificationSettingsService = notificationSettingsService, sessionCoroutineScope = sessionCoroutineScope, coroutineDispatchers = dispatchers, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapper.kt index 9ac5330294..57a3914253 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapper.kt @@ -22,11 +22,6 @@ import org.matrix.rustcomponents.sdk.BackupUploadState as RustBackupUploadState class BackupUploadStateMapper { fun map(rustEnableProgress: RustBackupUploadState): BackupUploadState { return when (rustEnableProgress) { - is RustBackupUploadState.CheckingIfUploadNeeded -> - BackupUploadState.CheckingIfUploadNeeded( - backedUpCount = rustEnableProgress.backedUpCount.toInt(), - totalCount = rustEnableProgress.totalCount.toInt(), - ) RustBackupUploadState.Done -> BackupUploadState.Done is RustBackupUploadState.Uploading -> diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapper.kt index a50a68267d..953c86d816 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapper.kt @@ -22,12 +22,14 @@ import org.matrix.rustcomponents.sdk.EnableRecoveryProgress as RustEnableRecover class EnableRecoveryProgressMapper { fun map(rustEnableProgress: RustEnableRecoveryProgress): EnableRecoveryProgress { return when (rustEnableProgress) { - is RustEnableRecoveryProgress.CreatingRecoveryKey -> EnableRecoveryProgress.CreatingRecoveryKey + is RustEnableRecoveryProgress.Starting -> EnableRecoveryProgress.Starting is RustEnableRecoveryProgress.CreatingBackup -> EnableRecoveryProgress.CreatingBackup + is RustEnableRecoveryProgress.CreatingRecoveryKey -> EnableRecoveryProgress.CreatingRecoveryKey is RustEnableRecoveryProgress.BackingUp -> EnableRecoveryProgress.BackingUp( backedUpCount = rustEnableProgress.backedUpCount.toInt(), totalCount = rustEnableProgress.totalCount.toInt(), ) + is RustEnableRecoveryProgress.RoomKeyUploadError -> EnableRecoveryProgress.RoomKeyUploadError is RustEnableRecoveryProgress.Done -> EnableRecoveryProgress.Done( recoveryKey = rustEnableProgress.recoveryKey ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt index 30b8c651a0..10929f0494 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RustEncryptionService.kt @@ -86,7 +86,7 @@ internal class RustEncryptionService( } }.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, RecoveryState.WAITING_FOR_SYNC) - override val enableRecoveryProgressStateFlow: MutableStateFlow = MutableStateFlow(EnableRecoveryProgress.Unknown) + override val enableRecoveryProgressStateFlow: MutableStateFlow = MutableStateFlow(EnableRecoveryProgress.Starting) fun start() { service.backupStateListener(object : BackupStateListener { @@ -181,7 +181,7 @@ internal class RustEncryptionService( override suspend fun fixRecoveryIssues(recoveryKey: String): Result = withContext(dispatchers.io) { runCatching { - service.fixRecoveryIssues(recoveryKey) + service.recover(recoveryKey) } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt index 331d3f8473..0dfcee7196 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/SteadyStateExceptionMapper.kt @@ -28,7 +28,7 @@ class SteadyStateExceptionMapper { is RustSteadyStateException.Connection -> SteadyStateException.Connection( message = data.message ) - is RustSteadyStateException.Laged -> SteadyStateException.Lagged( + is RustSteadyStateException.Lagged -> SteadyStateException.Lagged( message = data.message ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt index 2bfef368a9..f58a5c930d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt @@ -24,8 +24,8 @@ import io.element.android.libraries.matrix.impl.roomlist.roomOrNull import io.element.android.libraries.matrix.impl.timeline.runWithTimelineListenerRegistered import kotlinx.coroutines.CancellationException import kotlinx.coroutines.withTimeout -import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListService +import org.matrix.rustcomponents.sdk.Timeline import kotlin.time.Duration.Companion.milliseconds /** @@ -37,19 +37,19 @@ class RoomContentForwarder( ) { /** - * Forwards the event with the given [eventId] from the [fromRoom] to the given [toRoomIds]. - * @param fromRoom the room to forward the event from + * Forwards the event with the given [eventId] from the [fromTimeline] to the given [toRoomIds]. + * @param fromTimeline the room to forward the event from * @param eventId the id of the event to forward * @param toRoomIds the ids of the rooms to forward the event to * @param timeoutMs the maximum time in milliseconds to wait for the event to be sent to a room */ suspend fun forward( - fromRoom: Room, + fromTimeline: Timeline, eventId: EventId, toRoomIds: List, timeoutMs: Long = 5000L ) { - val content = fromRoom.getTimelineEventContentByEventId(eventId.value) + val content = fromTimeline.getTimelineEventContentByEventId(eventId.value) val targetSlidingSyncRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) } val targetRooms = targetSlidingSyncRooms.mapNotNull { slidingSyncRoom -> slidingSyncRoom.use { it.fullRoom() } } val failedForwardingTo = mutableSetOf() @@ -57,9 +57,9 @@ class RoomContentForwarder( room.use { targetRoom -> runCatching { // Sending a message requires a registered timeline listener - targetRoom.runWithTimelineListenerRegistered { + targetRoom.timeline().runWithTimelineListenerRegistered { withTimeout(timeoutMs.milliseconds) { - targetRoom.send(content) + targetRoom.timeline().send(content) } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt index 40b0f08798..6d8578ac0c 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustMatrixRoom.kt @@ -76,6 +76,7 @@ import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.RoomMember import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle +import org.matrix.rustcomponents.sdk.Timeline import org.matrix.rustcomponents.sdk.WidgetCapabilities import org.matrix.rustcomponents.sdk.WidgetCapabilitiesProvider import org.matrix.rustcomponents.sdk.messageEventContentFromHtml @@ -87,9 +88,10 @@ import java.io.File @OptIn(ExperimentalCoroutinesApi::class) class RustMatrixRoom( override val sessionId: SessionId, - isKeyBackupEnabled: Boolean, + private val isKeyBackupEnabled: Boolean, private val roomListItem: RoomListItem, private val innerRoom: Room, + private val innerTimeline: Timeline, private val roomNotificationSettingsService: RustNotificationSettingsService, sessionCoroutineScope: CoroutineScope, private val coroutineDispatchers: CoroutineDispatchers, @@ -130,7 +132,7 @@ class RustMatrixRoom( override val timeline = RustMatrixTimeline( isKeyBackupEnabled = isKeyBackupEnabled, matrixRoom = this, - innerRoom = innerRoom, + innerTimeline = innerTimeline, roomCoroutineScope = roomCoroutineScope, dispatcher = roomDispatcher, lastLoginTimestamp = sessionData.loginTimestamp, @@ -147,6 +149,7 @@ class RustMatrixRoom( override fun destroy() { roomCoroutineScope.cancel() + innerTimeline.destroy() innerRoom.destroy() roomListItem.destroy() specialModeEventTimelineItem?.destroy() @@ -254,7 +257,7 @@ class RustMatrixRoom( override suspend fun sendMessage(body: String, htmlBody: String?, mentions: List): Result = withContext(roomDispatcher) { messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()).use { content -> runCatching { - innerRoom.send(content) + innerTimeline.send(content) } } } @@ -269,9 +272,9 @@ class RustMatrixRoom( withContext(roomDispatcher) { if (originalEventId != null) { runCatching { - val editedEvent = specialModeEventTimelineItem ?: innerRoom.getEventTimelineItemByEventId(originalEventId.value) + val editedEvent = specialModeEventTimelineItem ?: innerTimeline.getEventTimelineItemByEventId(originalEventId.value) editedEvent.use { - innerRoom.edit( + innerTimeline.edit( newContent = messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()), editItem = it, ) @@ -281,7 +284,7 @@ class RustMatrixRoom( } else { runCatching { transactionId?.let { cancelSend(it) } - innerRoom.send(messageEventContentFromParts(body, htmlBody)) + innerTimeline.send(messageEventContentFromParts(body, htmlBody)) } } } @@ -292,15 +295,15 @@ class RustMatrixRoom( runCatching { specialModeEventTimelineItem?.destroy() specialModeEventTimelineItem = null - specialModeEventTimelineItem = eventId?.let { innerRoom.getEventTimelineItemByEventId(it.value) } + specialModeEventTimelineItem = eventId?.let { innerTimeline.getEventTimelineItemByEventId(it.value) } } } override suspend fun replyMessage(eventId: EventId, body: String, htmlBody: String?, mentions: List): Result = withContext(roomDispatcher) { runCatching { - val inReplyTo = specialModeEventTimelineItem ?: innerRoom.getEventTimelineItemByEventId(eventId.value) + val inReplyTo = specialModeEventTimelineItem ?: innerTimeline.getEventTimelineItemByEventId(eventId.value) inReplyTo.use { eventTimelineItem -> - innerRoom.sendReply(messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()), eventTimelineItem) + innerTimeline.sendReply(messageEventContentFromParts(body, htmlBody).withMentions(mentions.map()), eventTimelineItem) } specialModeEventTimelineItem = null } @@ -362,37 +365,37 @@ class RustMatrixRoom( override suspend fun sendImage(file: File, thumbnailFile: File, imageInfo: ImageInfo, progressCallback: ProgressCallback?): Result { return sendAttachment(listOf(file, thumbnailFile)) { - innerRoom.sendImage(file.path, thumbnailFile.path, imageInfo.map(), progressCallback?.toProgressWatcher()) + innerTimeline.sendImage(file.path, thumbnailFile.path, imageInfo.map(), progressCallback?.toProgressWatcher()) } } override suspend fun sendVideo(file: File, thumbnailFile: File, videoInfo: VideoInfo, progressCallback: ProgressCallback?): Result { return sendAttachment(listOf(file, thumbnailFile)) { - innerRoom.sendVideo(file.path, thumbnailFile.path, videoInfo.map(), progressCallback?.toProgressWatcher()) + innerTimeline.sendVideo(file.path, thumbnailFile.path, videoInfo.map(), progressCallback?.toProgressWatcher()) } } override suspend fun sendAudio(file: File, audioInfo: AudioInfo, progressCallback: ProgressCallback?): Result { return sendAttachment(listOf(file)) { - innerRoom.sendAudio(file.path, audioInfo.map(), progressCallback?.toProgressWatcher()) + innerTimeline.sendAudio(file.path, audioInfo.map(), progressCallback?.toProgressWatcher()) } } override suspend fun sendFile(file: File, fileInfo: FileInfo, progressCallback: ProgressCallback?): Result { return sendAttachment(listOf(file)) { - innerRoom.sendFile(file.path, fileInfo.map(), progressCallback?.toProgressWatcher()) + innerTimeline.sendFile(file.path, fileInfo.map(), progressCallback?.toProgressWatcher()) } } override suspend fun toggleReaction(emoji: String, eventId: EventId): Result = withContext(roomDispatcher) { runCatching { - innerRoom.toggleReaction(key = emoji, eventId = eventId.value) + innerTimeline.toggleReaction(key = emoji, eventId = eventId.value) } } override suspend fun forwardEvent(eventId: EventId, roomIds: List): Result = withContext(roomDispatcher) { runCatching { - roomContentForwarder.forward(fromRoom = innerRoom, eventId = eventId, toRoomIds = roomIds) + roomContentForwarder.forward(fromTimeline = innerTimeline, eventId = eventId, toRoomIds = roomIds) }.onFailure { Timber.e(it) } @@ -400,13 +403,13 @@ class RustMatrixRoom( override suspend fun retrySendMessage(transactionId: TransactionId): Result = withContext(roomDispatcher) { runCatching { - innerRoom.retrySend(transactionId.value) + innerTimeline.retrySend(transactionId.value) } } override suspend fun cancelSend(transactionId: TransactionId): Result = withContext(roomDispatcher) { runCatching { - innerRoom.cancelSend(transactionId.value) + innerTimeline.cancelSend(transactionId.value) } } @@ -451,7 +454,7 @@ class RustMatrixRoom( assetType: AssetType?, ): Result = withContext(roomDispatcher) { runCatching { - innerRoom.sendLocation( + innerTimeline.sendLocation( body = body, geoUri = geoUri, description = description, @@ -468,7 +471,7 @@ class RustMatrixRoom( pollKind: PollKind, ): Result = withContext(roomDispatcher) { runCatching { - innerRoom.createPoll( + innerTimeline.createPoll( question = question, answers = answers, maxSelections = maxSelections.toUByte(), @@ -486,11 +489,11 @@ class RustMatrixRoom( ): Result = withContext(roomDispatcher) { runCatching { val pollStartEvent = - innerRoom.getEventTimelineItemByEventId( + innerTimeline.getEventTimelineItemByEventId( eventId = pollStartId.value ) pollStartEvent.use { - innerRoom.editPoll( + innerTimeline.editPoll( question = question, answers = answers, maxSelections = maxSelections.toUByte(), @@ -506,7 +509,7 @@ class RustMatrixRoom( answers: List ): Result = withContext(roomDispatcher) { runCatching { - innerRoom.sendPollResponse( + innerTimeline.sendPollResponse( pollStartId = pollStartId.value, answers = answers, ) @@ -518,7 +521,7 @@ class RustMatrixRoom( text: String ): Result = withContext(roomDispatcher) { runCatching { - innerRoom.endPoll( + innerTimeline.endPoll( pollStartId = pollStartId.value, text = text, ) @@ -531,7 +534,7 @@ class RustMatrixRoom( waveform: List, progressCallback: ProgressCallback?, ): Result = sendAttachment(listOf(file)) { - innerRoom.sendVoiceMessage( + innerTimeline.sendVoiceMessage( url = file.path, audioInfo = audioInfo.map(), waveform = waveform.toMSC3246range(), @@ -560,6 +563,16 @@ class RustMatrixRoom( ) } + override suspend fun pollHistory() = RustMatrixTimeline( + isKeyBackupEnabled = isKeyBackupEnabled, + matrixRoom = this, + innerTimeline = innerRoom.pollHistory(), + roomCoroutineScope = roomCoroutineScope, + dispatcher = roomDispatcher, + lastLoginTimestamp = sessionData.loginTimestamp, + onNewSyncedEvent = { _syncUpdateFlow.value = systemClock.epochMillis() } + ) + private suspend fun sendAttachment(files: List, handle: () -> SendAttachmentJoinHandle): Result { return runCatching { MediaUploadHandlerImpl(files, handle()) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt index e87ae74f30..8eb2f999d1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RoomTimelineExtensions.kt @@ -29,29 +29,28 @@ import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.catch import org.matrix.rustcomponents.sdk.BackPaginationStatus import org.matrix.rustcomponents.sdk.BackPaginationStatusListener -import org.matrix.rustcomponents.sdk.Room +import org.matrix.rustcomponents.sdk.Timeline import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineItem import org.matrix.rustcomponents.sdk.TimelineListener import timber.log.Timber -internal fun Room.timelineDiffFlow(onInitialList: suspend (List) -> Unit): Flow> = +internal fun Timeline.timelineDiffFlow(onInitialList: suspend (List) -> Unit): Flow> = callbackFlow { val listener = object : TimelineListener { override fun onUpdate(diff: List) { trySendBlocking(diff) } } - val roomId = id() - Timber.d("Open timelineDiffFlow for room $roomId") - val result = addTimelineListener(listener) + Timber.d("Open timelineDiffFlow for TimelineInterface ${this@timelineDiffFlow}") + val result = addListener(listener) try { onInitialList(result.items) } catch (exception: Exception) { - Timber.d(exception, "Catch failure in timelineDiffFlow of room $roomId") + Timber.d(exception, "Catch failure in timelineDiffFlow of TimelineInterface ${this@timelineDiffFlow}") } awaitClose { - Timber.d("Close timelineDiffFlow for room $roomId") + Timber.d("Close timelineDiffFlow for TimelineInterface ${this@timelineDiffFlow}") result.itemsStream.cancelAndDestroy() result.items.destroyAll() } @@ -59,7 +58,7 @@ internal fun Room.timelineDiffFlow(onInitialList: suspend (List) - Timber.d(it, "timelineDiffFlow() failed") }.buffer(Channel.UNLIMITED) -internal fun Room.backPaginationStatusFlow(): Flow = +internal fun Timeline.backPaginationStatusFlow(): Flow = mxCallbackFlow { val listener = object : BackPaginationStatusListener { override fun onUpdate(status: BackPaginationStatus) { @@ -71,8 +70,8 @@ internal fun Room.backPaginationStatusFlow(): Flow = } }.buffer(Channel.UNLIMITED) -internal suspend fun Room.runWithTimelineListenerRegistered(action: suspend () -> Unit) { - val result = addTimelineListener(NoOpTimelineListener) +internal suspend fun Timeline.runWithTimelineListenerRegistered(action: suspend () -> Unit) { + val result = addListener(NoOpTimelineListener) try { action() } finally { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt index 85e6905f0a..85f59f9e57 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustMatrixTimeline.kt @@ -46,7 +46,7 @@ import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.BackPaginationStatus import org.matrix.rustcomponents.sdk.EventItemOrigin import org.matrix.rustcomponents.sdk.PaginationOptions -import org.matrix.rustcomponents.sdk.Room +import org.matrix.rustcomponents.sdk.Timeline import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineItem import timber.log.Timber @@ -59,9 +59,9 @@ class RustMatrixTimeline( roomCoroutineScope: CoroutineScope, isKeyBackupEnabled: Boolean, private val matrixRoom: MatrixRoom, - private val innerRoom: Room, + private val innerTimeline: Timeline, private val dispatcher: CoroutineDispatcher, - private val lastLoginTimestamp: Date?, + lastLoginTimestamp: Date?, private val onNewSyncedEvent: () -> Unit, ) : MatrixTimeline { @@ -109,7 +109,7 @@ class RustMatrixTimeline( Timber.d("Initialize timeline for room ${matrixRoom.roomId}") roomCoroutineScope.launch(dispatcher) { - innerRoom.timelineDiffFlow { initialList -> + innerTimeline.timelineDiffFlow { initialList -> postItems(initialList) }.onEach { diffs -> if (diffs.any { diff -> diff.eventOrigin() == EventItemOrigin.SYNC }) { @@ -118,7 +118,7 @@ class RustMatrixTimeline( postDiffs(diffs) }.launchIn(this) - innerRoom.backPaginationStatusFlow() + innerTimeline.backPaginationStatusFlow() .onEach { postPaginationStatus(it) } @@ -130,7 +130,7 @@ class RustMatrixTimeline( private suspend fun fetchMembers() = withContext(dispatcher) { initLatch.await() - innerRoom.fetchMembers() + innerTimeline.fetchMembers() } @OptIn(ExperimentalCoroutinesApi::class) @@ -188,7 +188,7 @@ class RustMatrixTimeline( override suspend fun fetchDetailsForEvent(eventId: EventId): Result = withContext(dispatcher) { runCatching { - innerRoom.fetchDetailsForEvent(eventId.value) + innerTimeline.fetchDetailsForEvent(eventId.value) } } @@ -201,7 +201,7 @@ class RustMatrixTimeline( items = untilNumberOfItems.toUShort(), waitForToken = true, ) - innerRoom.paginateBackwards(paginationOptions) + innerTimeline.paginateBackwards(paginationOptions) }.onFailure { error -> if (error is TimelineException.CannotPaginate) { Timber.d("Can't paginate backwards on room ${matrixRoom.roomId}, we're already at the start") @@ -219,10 +219,14 @@ class RustMatrixTimeline( override suspend fun sendReadReceipt(eventId: EventId) = withContext(dispatcher) { runCatching { - innerRoom.sendReadReceipt(eventId = eventId.value) + innerTimeline.sendReadReceipt(eventId = eventId.value) } } + override fun close() { + innerTimeline.close() + } + fun getItemById(eventId: EventId): MatrixTimelineItem.Event? { return _timelineItems.value.firstOrNull { (it as? MatrixTimelineItem.Event)?.eventId == eventId } as? MatrixTimelineItem.Event } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt index 9f10f4ba35..f8a2d411fe 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/encryption/FakeEncryptionService.kt @@ -30,7 +30,7 @@ class FakeEncryptionService : EncryptionService { private var disableRecoveryFailure: Exception? = null override val backupStateStateFlow: MutableStateFlow = MutableStateFlow(BackupState.UNKNOWN) override val recoveryStateStateFlow: MutableStateFlow = MutableStateFlow(RecoveryState.UNKNOWN) - override val enableRecoveryProgressStateFlow: MutableStateFlow = MutableStateFlow(EnableRecoveryProgress.Unknown) + override val enableRecoveryProgressStateFlow: MutableStateFlow = MutableStateFlow(EnableRecoveryProgress.Starting) private var waitForBackupUploadSteadyStateFlow: Flow = flowOf() private var fixRecoveryIssuesFailure: Exception? = null diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 531c792713..17c351945f 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -425,6 +425,9 @@ class FakeMatrixRoom( ): Result = generateWidgetWebViewUrlResult override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result = getWidgetDriverResult + override suspend fun pollHistory(): MatrixTimeline { + return FakeMatrixTimeline() + } fun givenLeaveRoomError(throwable: Throwable?) { this.leaveRoomError = throwable diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeMatrixTimeline.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeMatrixTimeline.kt index 6cf6f05cbe..21325d7a83 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeMatrixTimeline.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/timeline/FakeMatrixTimeline.kt @@ -79,4 +79,6 @@ class FakeMatrixTimeline( sendReadReceiptLatch?.complete(Unit) Result.success(Unit) } + + override fun close() = Unit }