diff --git a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt index abb6682a66..ffe98680dd 100644 --- a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt +++ b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import kotlin.jvm.optionals.getOrElse class RoomAliasResolverPresenter @AssistedInject constructor( @Assisted private val roomAlias: RoomAlias, @@ -57,7 +58,9 @@ class RoomAliasResolverPresenter @AssistedInject constructor( private fun CoroutineScope.resolveAlias(resolveState: MutableState>) = launch { suspend { - matrixClient.resolveRoomAlias(roomAlias).getOrThrow() + matrixClient.resolveRoomAlias(roomAlias) + .getOrThrow() + .getOrElse { error("Failed to resolve room alias $roomAlias") } }.runCatchingUpdatingState(resolveState) } } diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt index e651cf41e8..9894c2b342 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenterTest.kt @@ -24,6 +24,7 @@ import io.element.android.tests.testutils.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import java.util.Optional class RoomAliasResolverPresenterTest { @get:Rule @@ -42,7 +43,7 @@ class RoomAliasResolverPresenterTest { @Test fun `present - resolve alias to roomId`() = runTest { - val result = aResolvedRoomAlias() + val result = Optional.of(aResolvedRoomAlias()) val client = FakeMatrixClient( resolveRoomAliasResult = { Result.success(result) } ) @@ -54,7 +55,7 @@ class RoomAliasResolverPresenterTest { assertThat(awaitItem().resolveState.isLoading()).isTrue() val resultState = awaitItem() assertThat(resultState.roomAlias).isEqualTo(A_ROOM_ALIAS) - assertThat(resultState.resolveState.dataOrNull()).isEqualTo(result) + assertThat(resultState.resolveState.dataOrNull()).isEqualTo(result.get()) } } diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt index 2f3b0cff75..a5b62ff1e3 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt @@ -28,6 +28,8 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import javax.inject.Inject +private const val SEARCH_BATCH_SIZE = 20 + class RoomDirectoryPresenter @Inject constructor( private val dispatchers: CoroutineDispatchers, private val roomDirectoryService: RoomDirectoryService, @@ -51,7 +53,7 @@ class RoomDirectoryPresenter @Inject constructor( loadingMore = false // debounce search query delay(300) - roomDirectoryList.filter(searchQuery, 20) + roomDirectoryList.filter(filter = searchQuery, batchSize = SEARCH_BATCH_SIZE, viaServerName = null) } LaunchedEffect(loadingMore) { if (loadingMore) { diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt index 10dda624bd..20a709bce7 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt @@ -81,7 +81,7 @@ import org.junit.Test @Test fun `present - emit search event`() = runTest { - val filterLambda = lambdaRecorder { _: String?, _: Int -> + val filterLambda = lambdaRecorder { _: String?, _: Int, _: String? -> Result.success(Unit) } val roomDirectoryList = FakeRoomDirectoryList(filterLambda = filterLambda) @@ -99,7 +99,7 @@ import org.junit.Test } assert(filterLambda) .isCalledOnce() - .with(value("test"), any()) + .with(value("test"), any(), value(null)) } @Test diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 6af1763e83..504db1c6d9 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -108,7 +108,14 @@ interface MatrixClient : Closeable { suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result suspend fun getRecentlyVisitedRooms(): Result> - suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result + + /** + * Resolves the given room alias to a roomID (and a list of servers), if possible. + * @param roomAlias the room alias to resolve + * @return the resolved room alias if any, an empty result if not found,or an error if the resolution failed. + * + */ + suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result> /** * Enables or disables the sending queue, according to the given parameter. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt index 5f362dfda5..88cabf265b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomdirectory/RoomDirectoryList.kt @@ -10,8 +10,22 @@ package io.element.android.libraries.matrix.api.roomdirectory import kotlinx.coroutines.flow.Flow interface RoomDirectoryList { - suspend fun filter(filter: String?, batchSize: Int): Result + /** + * Starts a filtered search for the server. + * If the filter is not provided it will search for all the rooms. You can specify a batch_size to control the number of rooms to fetch per request. + * If the via_server is not provided it will search in the current homeserver by default. + * This method will clear the current search results and start a new one + */ + suspend fun filter(filter: String?, batchSize: Int, viaServerName: String?): Result + + /** + * Load more rooms from the current search results. + */ suspend fun loadMore(): Result + + /** + * The current search results as a state flow. + */ val state: Flow data class State( 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 101d049659..375d704ef9 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 @@ -71,7 +71,6 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.Channel @@ -112,7 +111,6 @@ import org.matrix.rustcomponents.sdk.RoomPreset as RustRoomPreset import org.matrix.rustcomponents.sdk.RoomVisibility as RustRoomVisibility import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService -@OptIn(ExperimentalCoroutinesApi::class) class RustMatrixClient( private val client: Client, private val baseDirectory: File, @@ -420,13 +418,15 @@ class RustMatrixClient( } } - override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result = withContext(sessionDispatcher) { + override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result> = withContext(sessionDispatcher) { runCatching { - val result = client.resolveRoomAlias(roomAlias.value) - ResolvedRoomAlias( - roomId = RoomId(result.roomId), - servers = result.servers, - ) + val result = client.resolveRoomAlias(roomAlias.value)?.let { + ResolvedRoomAlias( + roomId = RoomId(it.roomId), + servers = it.servers, + ) + } + Optional.ofNullable(result) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt index 7219e9c3ed..576b93d26d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt @@ -41,9 +41,9 @@ class RustRoomDirectoryList( .launchIn(coroutineScope) } - override suspend fun filter(filter: String?, batchSize: Int): Result { + override suspend fun filter(filter: String?, batchSize: Int, viaServerName: String?): Result { return execute { - inner.search(filter = filter, batchSize = batchSize.toUInt()) + inner.search(filter = filter, batchSize = batchSize.toUInt(), viaServerName = viaServerName) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt index 0569ee55c8..42e078d1c8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomDirectorySearch.kt @@ -21,7 +21,7 @@ class FakeRustRoomDirectorySearch( return isAtLastPage } - override suspend fun search(filter: String?, batchSize: UInt) = simulateLongTask { } + override suspend fun search(filter: String?, batchSize: UInt, viaServerName: String?) = simulateLongTask { } override suspend fun nextPage() = simulateLongTask { } private var listener: RoomDirectorySearchEntriesListener? = null diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt index 134b90adc9..0eca9edde5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt @@ -36,7 +36,7 @@ class RustRoomDirectoryListTest { // Let the mxCallback be ready runCurrent() sut.state.test { - sut.filter("", 20) + sut.filter(filter = "", batchSize = 20, viaServerName = null) roomDirectorySearch.emitResult( listOf( RoomDirectorySearchEntryUpdate.Append(listOf(aRustRoomDescription())) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 2c69048c39..dd7869cdf7 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -73,7 +73,11 @@ class FakeMatrixClient( private val encryptionService: FakeEncryptionService = FakeEncryptionService(), private val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(), private val accountManagementUrlString: Result = Result.success(null), - private val resolveRoomAliasResult: (RoomAlias) -> Result = { Result.success(ResolvedRoomAlias(A_ROOM_ID, emptyList())) }, + private val resolveRoomAliasResult: (RoomAlias) -> Result> = { + Result.success( + Optional.of(ResolvedRoomAlias(A_ROOM_ID, emptyList())) + ) + }, private val getRoomPreviewResult: (RoomIdOrAlias, List) -> Result = { _, _ -> Result.failure(AN_EXCEPTION) }, private val clearCacheLambda: () -> Unit = { lambdaError() }, private val userIdServerNameLambda: () -> String = { lambdaError() }, @@ -305,7 +309,7 @@ class FakeMatrixClient( return Result.success(Unit) } - override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result = simulateLongTask { + override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result> = simulateLongTask { resolveRoomAliasResult(roomAlias) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt index afe1e52074..6a3fcb3b45 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/roomdirectory/FakeRoomDirectoryList.kt @@ -13,10 +13,10 @@ import kotlinx.coroutines.flow.emptyFlow class FakeRoomDirectoryList( override val state: Flow = emptyFlow(), - val filterLambda: (String?, Int) -> Result = { _, _ -> Result.success(Unit) }, + val filterLambda: (String?, Int, String?) -> Result = { _, _, _ -> Result.success(Unit) }, val loadMoreLambda: () -> Result = { Result.success(Unit) } ) : RoomDirectoryList { - override suspend fun filter(filter: String?, batchSize: Int) = filterLambda(filter, batchSize) + override suspend fun filter(filter: String?, batchSize: Int, viaServerName: String?): Result = filterLambda(filter, batchSize, viaServerName) override suspend fun loadMore(): Result = loadMoreLambda() }