From a87bbdd91cd22b23c451355ba02ada089b4254cb Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 5 Aug 2025 17:14:51 +0200 Subject: [PATCH] Delegate call notifications to Element Call, upgrade SDK and EC embedded (#5119) * Stop sending call notifications manually: the Element Call widget can now assume responsibility for sending them when you start a call. * Upgrade SDK version to `v25.8.5`, fix API breaks * Upgrade Element Call embedded to `v0.14.1` * Fix tests and lint issues * Add `RoomListEntriesDynamicFilterKind.NonSpace` to avoid displaying spaces in the room list --------- Co-authored-by: Robin --- .../call/impl/ui/CallScreenPresenter.kt | 35 +------------ .../impl/utils/DefaultCallWidgetProvider.kt | 3 +- .../call/ui/CallScreenPresenterTest.kt | 14 +----- gradle/libs.versions.toml | 4 +- .../libraries/matrix/api/room/JoinedRoom.kt | 5 -- .../api/widget/CallWidgetSettingsProvider.kt | 1 + .../matrix/impl/room/JoinedRustRoom.kt | 6 --- .../matrix/impl/roomlist/RoomListFactory.kt | 1 + .../timeline/MatrixTimelineDiffProcessor.kt | 49 +++++++++---------- .../matrix/impl/timeline/TimelineDiffExt.kt | 27 +++------- .../DefaultCallWidgetSettingsProvider.kt | 4 +- .../fixtures/fakes/FakeFfiTimelineDiff.kt | 30 ------------ .../MatrixTimelineDiffProcessorTest.kt | 26 +++++----- .../matrix/impl/timeline/RustTimelineTest.kt | 8 +-- .../timeline/TimelineItemsSubscriberTest.kt | 14 +++--- .../matrix/test/room/FakeJoinedRoom.kt | 5 -- .../widget/FakeCallWidgetSettingsProvider.kt | 6 +-- 17 files changed, 64 insertions(+), 174 deletions(-) delete mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiTimelineDiff.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt index 04999c82ab..0164bb3089 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenPresenter.kt @@ -33,14 +33,11 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClientProvider -import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.sync.SyncState import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.services.analytics.api.ScreenTracker -import io.element.android.services.appnavstate.api.ActiveRoomsHolder import io.element.android.services.appnavstate.api.AppForegroundStateService import io.element.android.services.toolbox.api.systemclock.SystemClock import kotlinx.coroutines.CoroutineScope @@ -64,7 +61,6 @@ class CallScreenPresenter @AssistedInject constructor( private val activeCallManager: ActiveCallManager, private val languageTagProvider: LanguageTagProvider, private val appForegroundStateService: AppForegroundStateService, - private val activeRoomsHolder: ActiveRoomsHolder, @AppCoroutineScope private val appCoroutineScope: CoroutineScope, ) : Presenter { @@ -75,7 +71,6 @@ class CallScreenPresenter @AssistedInject constructor( private val isInWidgetMode = callType is CallType.RoomCall private val userAgent = userAgentProvider.provide() - private var notifiedCallStart = false @Composable override fun present(): CallScreenState { @@ -248,9 +243,7 @@ class CallScreenPresenter @AssistedInject constructor( Timber.d("Observing sync state in-call for sessionId: ${roomCallType.sessionId}") client.syncService().syncState .collect { state -> - if (state == SyncState.Running) { - client.notifyCallStartIfNeeded(callType.roomId) - } else { + if (state != SyncState.Running) { appForegroundStateService.updateIsInCallState(true) } } @@ -263,32 +256,6 @@ class CallScreenPresenter @AssistedInject constructor( } } - private suspend fun MatrixClient.notifyCallStartIfNeeded(roomId: RoomId) { - if (notifiedCallStart) return - - val activeRoomForSession = activeRoomsHolder.getActiveRoomMatching(sessionId, roomId) - val sendCallNotificationResult = if (activeRoomForSession != null) { - Timber.d("Notifying call start for room $roomId. Has room call: ${activeRoomForSession.info().hasRoomCall}") - activeRoomForSession.sendCallNotificationIfNeeded() - } else { - // Instantiate the room from the session and roomId and send the notification - getJoinedRoom(roomId)?.use { room -> - Timber.d("Notifying call start for room $roomId. Has room call: ${room.info().hasRoomCall}") - room.sendCallNotificationIfNeeded() - } ?: run { - Timber.w("No room found for session $sessionId and room $roomId, skipping call notification.") - return - } - } - - sendCallNotificationResult.fold( - onSuccess = { notifiedCallStart = true }, - onFailure = { error -> - Timber.e(error, "Failed to send call notification for room $roomId.") - } - ) - } - private fun parseMessage(message: String): WidgetMessage? { return WidgetMessageSerializer.deserialize(message).getOrNull() } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt index d87826fe46..f5d50ecfe6 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.services.appnavstate.api.ActiveRoomsHolder @@ -44,7 +45,7 @@ class DefaultCallWidgetProvider @Inject constructor( val baseUrl = customBaseUrl ?: EMBEDDED_CALL_WIDGET_BASE_URL val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() - val widgetSettings = callWidgetSettingsProvider.provide(baseUrl, encrypted = isEncrypted) + val widgetSettings = callWidgetSettingsProvider.provide(baseUrl, encrypted = isEncrypted, direct = room.isDm()) val callUrl = room.generateWidgetWebViewUrl( widgetSettings = widgetSettings, clientId = clientId, diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt index 7709066dd0..15f1334773 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt @@ -26,13 +26,11 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClientProvider -import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.sync.FakeSyncService import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.services.analytics.api.ScreenTracker import io.element.android.services.analytics.test.FakeScreenTracker -import io.element.android.services.appnavstate.api.ActiveRoomsHolder import io.element.android.services.appnavstate.test.FakeAppForegroundStateService import io.element.android.services.toolbox.api.systemclock.SystemClock import io.element.android.tests.testutils.WarmUpRule @@ -82,19 +80,12 @@ import kotlin.time.Duration.Companion.seconds } @Test - fun `present - with CallType RoomCall sets call as active, loads URL, runs WidgetDriver and notifies the other clients a call started`() = runTest { - val sendCallNotificationIfNeededLambda = lambdaRecorder> { Result.success(true) } - val syncService = FakeSyncService(SyncState.Running) - val fakeRoom = FakeJoinedRoom(sendCallNotificationIfNeededResult = sendCallNotificationIfNeededLambda) - val client = FakeMatrixClient(syncService = syncService).apply { - givenGetRoomResult(A_ROOM_ID, fakeRoom) - } + fun `present - with CallType RoomCall sets call as active, loads URL and runs WidgetDriver`() = runTest { val widgetDriver = FakeMatrixWidgetDriver() val widgetProvider = FakeCallWidgetProvider(widgetDriver) val analyticsLambda = lambdaRecorder {} val joinedCallLambda = lambdaRecorder {} val presenter = createCallScreenPresenter( - matrixClientsProvider = FakeMatrixClientProvider(getClient = { Result.success(client) }), callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID), widgetDriver = widgetDriver, widgetProvider = widgetProvider, @@ -116,7 +107,6 @@ import kotlin.time.Duration.Companion.seconds assertThat(widgetProvider.getWidgetCalled).isTrue() assertThat(widgetDriver.runCalledCount).isEqualTo(1) analyticsLambda.assertions().isCalledOnce().with(value(MobileScreen.ScreenName.RoomCall)) - sendCallNotificationIfNeededLambda.assertions().isCalledOnce() // Wait until the WidgetDriver is loaded skipItems(1) @@ -399,7 +389,6 @@ import kotlin.time.Duration.Companion.seconds activeCallManager: FakeActiveCallManager = FakeActiveCallManager(), screenTracker: ScreenTracker = FakeScreenTracker(), appForegroundStateService: FakeAppForegroundStateService = FakeAppForegroundStateService(), - activeRoomsHolder: ActiveRoomsHolder = ActiveRoomsHolder(), ): CallScreenPresenter { val userAgentProvider = object : UserAgentProvider { override fun provide(): String { @@ -420,7 +409,6 @@ import kotlin.time.Duration.Companion.seconds languageTagProvider = FakeLanguageTagProvider("en-US"), appForegroundStateService = appForegroundStateService, appCoroutineScope = backgroundScope, - activeRoomsHolder = activeRoomsHolder, ) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a4bb4fbee8..33834ed2f5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -176,7 +176,7 @@ jsoup = "org.jsoup:jsoup:1.21.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.1.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.7.28" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:25.8.5" 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" } @@ -215,7 +215,7 @@ anvil_compiler_api = { module = "dev.zacsweers.anvil:compiler-api", version.ref anvil_compiler_utils = { module = "dev.zacsweers.anvil:compiler-utils", version.ref = "anvil" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.13.1" +element_call_embedded = "io.element.android:element-call-embedded:0.14.1" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt index e6d17e27a5..fae6b04a93 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/JoinedRoom.kt @@ -156,11 +156,6 @@ interface JoinedRoom : BaseRoom { */ fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result - /** - * Send an Element Call started notification if needed. - */ - suspend fun sendCallNotificationIfNeeded(): Result - suspend fun setSendQueueEnabled(enabled: Boolean) /** diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt index c87316a1dc..7a735bbf92 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/widget/CallWidgetSettingsProvider.kt @@ -14,5 +14,6 @@ interface CallWidgetSettingsProvider { baseUrl: String, widgetId: String = UUID.randomUUID().toString(), encrypted: Boolean, + direct: Boolean, ): MatrixWidgetSettings } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt index a7dc2523ad..889c583c4e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt @@ -428,12 +428,6 @@ class JoinedRustRoom( } } - override suspend fun sendCallNotificationIfNeeded(): Result = withContext(roomDispatcher) { - runCatchingExceptions { - innerRoom.sendCallNotificationIfNeeded() - } - } - override suspend fun setSendQueueEnabled(enabled: Boolean) { withContext(roomDispatcher) { Timber.d("setSendQueuesEnabled: $enabled") diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt index 53b8127ab8..15ba644fcf 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt @@ -29,6 +29,7 @@ import org.matrix.rustcomponents.sdk.RoomList as InnerRoomList private val ROOM_LIST_RUST_FILTERS = listOf( RoomListEntriesDynamicFilterKind.NonLeft, + RoomListEntriesDynamicFilterKind.NonSpace, RoomListEntriesDynamicFilterKind.DeduplicateVersions ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt index 2088b6bc1d..eb27f2d667 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import org.matrix.rustcomponents.sdk.TimelineChange import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineItem import timber.log.Timber @@ -49,13 +48,13 @@ internal class MatrixTimelineDiffProcessor( } private fun MutableList.applyDiff(diff: TimelineDiff) { - when (diff.change()) { - TimelineChange.APPEND -> { - val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return + when (diff) { + is TimelineDiff.Append -> { + val items = diff.values.map { it.asMatrixTimelineItem() } addAll(items) } - TimelineChange.PUSH_BACK -> { - val item = diff.pushBack()?.asMatrixTimelineItem() ?: return + is TimelineDiff.PushBack -> { + val item = diff.value.asMatrixTimelineItem() if (item is MatrixTimelineItem.Event && item.event.content is RoomMembershipContent) { // TODO - This is a temporary solution to notify the room screen about membership changes // Ideally, this should be implemented by the Rust SDK @@ -63,41 +62,37 @@ internal class MatrixTimelineDiffProcessor( } add(item) } - TimelineChange.PUSH_FRONT -> { - val item = diff.pushFront()?.asMatrixTimelineItem() ?: return + is TimelineDiff.PushFront -> { + val item = diff.value.asMatrixTimelineItem() add(0, item) } - TimelineChange.SET -> { - val updateAtData = diff.set() ?: return - val item = updateAtData.item.asMatrixTimelineItem() - set(updateAtData.index.toInt(), item) + is TimelineDiff.Set -> { + val item = diff.value.asMatrixTimelineItem() + set(diff.index.toInt(), item) } - TimelineChange.INSERT -> { - val insertAtData = diff.insert() ?: return - val item = insertAtData.item.asMatrixTimelineItem() - add(insertAtData.index.toInt(), item) + is TimelineDiff.Insert -> { + val item = diff.value.asMatrixTimelineItem() + add(diff.index.toInt(), item) } - TimelineChange.REMOVE -> { - val removeAtData = diff.remove() ?: return - removeAt(removeAtData.toInt()) + is TimelineDiff.Remove -> { + removeAt(diff.index.toInt()) } - TimelineChange.RESET -> { + is TimelineDiff.Reset -> { clear() - val items = diff.reset()?.map { it.asMatrixTimelineItem() } ?: return + val items = diff.values.map { it.asMatrixTimelineItem() } addAll(items) } - TimelineChange.POP_FRONT -> { + TimelineDiff.PopFront -> { removeFirstOrNull() } - TimelineChange.POP_BACK -> { + TimelineDiff.PopBack -> { removeLastOrNull() } - TimelineChange.CLEAR -> { + TimelineDiff.Clear -> { clear() } - TimelineChange.TRUNCATE -> { - val index = diff.truncate() ?: return - subList(index.toInt(), size).clear() + is TimelineDiff.Truncate -> { + subList(diff.length.toInt(), size).clear() } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineDiffExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineDiffExt.kt index 6e79faae32..2da28399f6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineDiffExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineDiffExt.kt @@ -7,7 +7,6 @@ package io.element.android.libraries.matrix.impl.timeline -import org.matrix.rustcomponents.sdk.TimelineChange import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineItem import uniffi.matrix_sdk_ui.EventItemOrigin @@ -17,25 +16,13 @@ import uniffi.matrix_sdk_ui.EventItemOrigin * If there is multiple events in the diff, uses the first one as it should be a good indicator. */ internal fun TimelineDiff.eventOrigin(): EventItemOrigin? { - return when (change()) { - TimelineChange.APPEND -> { - append()?.firstOrNull()?.eventOrigin() - } - TimelineChange.PUSH_BACK -> { - pushBack()?.eventOrigin() - } - TimelineChange.PUSH_FRONT -> { - pushFront()?.eventOrigin() - } - TimelineChange.SET -> { - set()?.item?.eventOrigin() - } - TimelineChange.INSERT -> { - insert()?.item?.eventOrigin() - } - TimelineChange.RESET -> { - reset()?.firstOrNull()?.eventOrigin() - } + return when (this) { + is TimelineDiff.Append -> values.firstOrNull()?.eventOrigin() + is TimelineDiff.PushBack -> value.eventOrigin() + is TimelineDiff.PushFront -> value.eventOrigin() + is TimelineDiff.Set -> value.eventOrigin() + is TimelineDiff.Insert -> value.eventOrigin() + is TimelineDiff.Reset -> values.firstOrNull()?.eventOrigin() else -> null } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt index 90b3c16906..863dd6f0a2 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/widget/DefaultCallWidgetSettingsProvider.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.first import org.matrix.rustcomponents.sdk.newVirtualElementCallWidget import uniffi.matrix_sdk.EncryptionSystem import uniffi.matrix_sdk.HeaderStyle +import uniffi.matrix_sdk.NotificationType import uniffi.matrix_sdk.VirtualElementCallWidgetOptions import javax.inject.Inject import uniffi.matrix_sdk.Intent as CallIntent @@ -29,7 +30,7 @@ class DefaultCallWidgetSettingsProvider @Inject constructor( private val callAnalyticsCredentialsProvider: CallAnalyticCredentialsProvider, private val analyticsService: AnalyticsService, ) : CallWidgetSettingsProvider { - override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean): MatrixWidgetSettings { + override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean): MatrixWidgetSettings { val isAnalyticsEnabled = analyticsService.userConsentFlow.first() val options = VirtualElementCallWidgetOptions( elementCallUrl = baseUrl, @@ -53,6 +54,7 @@ class DefaultCallWidgetSettingsProvider @Inject constructor( hideHeader = true, controlledMediaDevices = true, header = HeaderStyle.APP_BAR, + sendNotificationType = if (direct) NotificationType.RING else NotificationType.NOTIFICATION, ) val rustWidgetSettings = newVirtualElementCallWidget(options) return MatrixWidgetSettings.fromRustWidgetSettings(rustWidgetSettings) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiTimelineDiff.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiTimelineDiff.kt deleted file mode 100644 index 605d2d6815..0000000000 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiTimelineDiff.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2024 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. - */ - -package io.element.android.libraries.matrix.impl.fixtures.fakes - -import org.matrix.rustcomponents.sdk.InsertData -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.SetData -import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiff -import org.matrix.rustcomponents.sdk.TimelineItem - -class FakeFfiTimelineDiff( - private val change: TimelineChange, - private val item: TimelineItem? = FakeFfiTimelineItem() -) : TimelineDiff(NoPointer) { - override fun change() = change - override fun append(): List? = item?.let { listOf(it) } - override fun insert(): InsertData? = item?.let { InsertData(1u, it) } - override fun pushBack(): TimelineItem? = item - override fun pushFront(): TimelineItem? = item - override fun remove(): UInt? = 1u - override fun reset(): List? = item?.let { listOf(it) } - override fun set(): SetData? = item?.let { SetData(1u, it) } - override fun truncate(): UInt? = 1u -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt index a4029417cf..b82c8dfbfb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt @@ -9,7 +9,7 @@ package io.element.android.libraries.matrix.impl.timeline import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem -import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimelineDiff +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimelineItem import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper @@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiff class MatrixTimelineDiffProcessorTest { private val timelineItems = MutableStateFlow>(emptyList()) @@ -33,7 +33,7 @@ class MatrixTimelineDiffProcessorTest { fun `Append adds new entries at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.APPEND))) + processor.postDiffs(listOf(TimelineDiff.Append(listOf(FakeFfiTimelineItem())))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -45,7 +45,7 @@ class MatrixTimelineDiffProcessorTest { fun `PushBack adds a new entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.PUSH_BACK))) + processor.postDiffs(listOf(TimelineDiff.PushBack(FakeFfiTimelineItem()))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -57,7 +57,7 @@ class MatrixTimelineDiffProcessorTest { fun `PushFront inserts a new entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.PUSH_FRONT))) + processor.postDiffs(listOf(TimelineDiff.PushFront(FakeFfiTimelineItem()))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( MatrixTimelineItem.Other, @@ -69,7 +69,7 @@ class MatrixTimelineDiffProcessorTest { fun `Set replaces an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.SET))) + processor.postDiffs(listOf(TimelineDiff.Set(1u, FakeFfiTimelineItem()))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -81,7 +81,7 @@ class MatrixTimelineDiffProcessorTest { fun `Insert inserts a new entry at the provided index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.INSERT))) + processor.postDiffs(listOf(TimelineDiff.Insert(1u, FakeFfiTimelineItem()))) assertThat(timelineItems.value.count()).isEqualTo(3) assertThat(timelineItems.value).containsExactly( anEvent, @@ -94,7 +94,7 @@ class MatrixTimelineDiffProcessorTest { fun `Remove removes an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.REMOVE))) + processor.postDiffs(listOf(TimelineDiff.Remove(1u))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -106,7 +106,7 @@ class MatrixTimelineDiffProcessorTest { fun `PopBack removes an entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.POP_BACK))) + processor.postDiffs(listOf(TimelineDiff.PopBack)) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent, @@ -117,7 +117,7 @@ class MatrixTimelineDiffProcessorTest { fun `PopFront removes an entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.POP_FRONT))) + processor.postDiffs(listOf(TimelineDiff.PopFront)) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent2, @@ -128,7 +128,7 @@ class MatrixTimelineDiffProcessorTest { fun `Clear removes all the entries`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.CLEAR))) + processor.postDiffs(listOf(TimelineDiff.Clear)) assertThat(timelineItems.value).isEmpty() } @@ -136,7 +136,7 @@ class MatrixTimelineDiffProcessorTest { fun `Truncate removes all entries after the provided length`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.TRUNCATE))) + processor.postDiffs(listOf(TimelineDiff.Truncate(1u))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent, @@ -147,7 +147,7 @@ class MatrixTimelineDiffProcessorTest { fun `Reset removes all entries and add the provided ones`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createMatrixTimelineDiffProcessor(timelineItems) - processor.postDiffs(listOf(FakeFfiTimelineDiff(change = TimelineChange.RESET))) + processor.postDiffs(listOf(TimelineDiff.Reset(listOf(FakeFfiTimelineItem())))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( MatrixTimelineItem.Other, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt index 8fcb352075..3fea130ece 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimelineTest.kt @@ -18,7 +18,6 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomListService import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimeline -import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimelineDiff import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.room.aRoomInfo @@ -33,7 +32,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiff import uniffi.matrix_sdk.RoomPaginationStatus import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline @@ -51,10 +50,7 @@ class RustTimelineTest { runCurrent() inner.emitDiff( listOf( - FakeFfiTimelineDiff( - item = null, - change = TimelineChange.RESET, - ) + TimelineDiff.Reset(emptyList()) ) ) with(awaitItem()) { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt index 03c1567c95..1df51dc5c2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt @@ -12,7 +12,6 @@ import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.impl.fixtures.factories.aRustEventTimelineItem import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimeline -import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimelineDiff import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiTimelineItem import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaRecorder @@ -24,7 +23,7 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test import org.matrix.rustcomponents.sdk.Timeline -import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiff import uniffi.matrix_sdk_ui.EventItemOrigin @OptIn(ExperimentalCoroutinesApi::class) @@ -42,7 +41,7 @@ class TimelineItemsSubscriberTest { timelineItemsSubscriber.subscribeIfNeeded() // Wait for the listener to be set. runCurrent() - timeline.emitDiff(listOf(FakeFfiTimelineDiff(item = null, change = TimelineChange.RESET))) + timeline.emitDiff(listOf(TimelineDiff.Reset(emptyList()))) val final = awaitItem() assertThat(final).isEmpty() timelineItemsSubscriber.unsubscribeIfNeeded() @@ -62,7 +61,7 @@ class TimelineItemsSubscriberTest { timelineItemsSubscriber.subscribeIfNeeded() // Wait for the listener to be set. runCurrent() - timeline.emitDiff(listOf(FakeFfiTimelineDiff(item = FakeFfiTimelineItem(), change = TimelineChange.RESET))) + timeline.emitDiff(listOf(TimelineDiff.Reset(listOf(FakeFfiTimelineItem())))) val final = awaitItem() assertThat(final).isNotEmpty() timelineItemsSubscriber.unsubscribeIfNeeded() @@ -86,11 +85,10 @@ class TimelineItemsSubscriberTest { runCurrent() timeline.emitDiff( listOf( - FakeFfiTimelineDiff( - item = FakeFfiTimelineItem( + TimelineDiff.Reset( + listOf(FakeFfiTimelineItem( asEventResult = aRustEventTimelineItem(origin = EventItemOrigin.SYNC), - ), - change = TimelineChange.RESET, + )) ) ) ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index c98c886129..4681937b42 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -55,7 +55,6 @@ class FakeJoinedRoom( private val roomNotificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), private var createTimelineResult: (CreateTimelineParams) -> Result = { lambdaError() }, private val editMessageLambda: (EventId, String, String?, List) -> Result = { _, _, _, _ -> lambdaError() }, - private val sendCallNotificationIfNeededResult: () -> Result = { lambdaError() }, private val progressCallbackValues: List> = emptyList(), private val generateWidgetWebViewUrlResult: (MatrixWidgetSettings, String, String?, String?) -> Result = { _, _, _, _ -> lambdaError() }, private val getWidgetDriverResult: (MatrixWidgetSettings) -> Result = { lambdaError() }, @@ -207,10 +206,6 @@ class FakeJoinedRoom( return getWidgetDriverResult(widgetSettings) } - override suspend fun sendCallNotificationIfNeeded(): Result = simulateLongTask { - sendCallNotificationIfNeededResult() - } - override suspend fun setSendQueueEnabled(enabled: Boolean) = simulateLongTask { setSendQueueEnabledResult(enabled) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt index 1b1c65abe3..d052a3d9b8 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/widget/FakeCallWidgetSettingsProvider.kt @@ -11,12 +11,12 @@ import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings class FakeCallWidgetSettingsProvider( - private val provideFn: (String, String) -> MatrixWidgetSettings = { _, _ -> MatrixWidgetSettings("id", true, "url") } + private val provideFn: (String, String, Boolean, Boolean) -> MatrixWidgetSettings = { _, _, _, _ -> MatrixWidgetSettings("id", true, "url") } ) : CallWidgetSettingsProvider { val providedBaseUrls = mutableListOf() - override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean): MatrixWidgetSettings { + override suspend fun provide(baseUrl: String, widgetId: String, encrypted: Boolean, direct: Boolean): MatrixWidgetSettings { providedBaseUrls += baseUrl - return provideFn(baseUrl, widgetId) + return provideFn(baseUrl, widgetId, encrypted, direct) } }