From ac7412c2d831ac0177cc8bc19300753c74e49255 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 2 Aug 2023 20:56:26 +0200 Subject: [PATCH] Feature/fga/matrix client versions (#1022) * Extract a RustMatrixClientFactory * Use serverVersions api on client builder to speed up startup. * Clean up * Fix compilation of sample --------- Co-authored-by: ganfra --- .../matrix/impl/RustMatrixClientFactory.kt | 78 +++++++++++++++++++ .../auth/RustMatrixAuthenticationService.kt | 51 ++---------- .../android/samples/minimal/MainActivity.kt | 22 ++++-- 3 files changed, 100 insertions(+), 51 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt new file mode 100644 index 0000000000..931133c266 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.impl + +import android.content.Context +import io.element.android.libraries.core.coroutine.CoroutineDispatchers +import io.element.android.libraries.di.ApplicationContext +import io.element.android.libraries.network.useragent.UserAgentProvider +import io.element.android.libraries.sessionstorage.api.SessionData +import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.services.toolbox.api.systemclock.SystemClock +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.withContext +import org.matrix.rustcomponents.sdk.ClientBuilder +import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.use +import java.io.File +import javax.inject.Inject + +class RustMatrixClientFactory @Inject constructor( + @ApplicationContext private val context: Context, + private val baseDirectory: File, + private val appCoroutineScope: CoroutineScope, + private val coroutineDispatchers: CoroutineDispatchers, + private val sessionStore: SessionStore, + private val userAgentProvider: UserAgentProvider, + private val clock: SystemClock, +) { + + suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { + val client = ClientBuilder() + .basePath(baseDirectory.absolutePath) + .homeserverUrl(sessionData.homeserverUrl) + .username(sessionData.userId) + .userAgent(userAgentProvider.provide()) + // FIXME Quick and dirty fix for stopping version requests on startup https://github.com/matrix-org/matrix-rust-sdk/pull/1376 + .serverVersions(listOf("v1.0", "v1.1", "v1.2", "v1.3", "v1.4", "v1.5")) + .use { it.build() } + + client.restoreSession(sessionData.toSession()) + + val syncService = client.syncService().finish() + + RustMatrixClient( + client = client, + syncService = syncService, + sessionStore = sessionStore, + appCoroutineScope = appCoroutineScope, + dispatchers = coroutineDispatchers, + baseDirectory = baseDirectory, + baseCacheDirectory = context.cacheDir, + clock = clock, + ) + } +} + +private fun SessionData.toSession() = Session( + accessToken = accessToken, + refreshToken = refreshToken, + userId = userId, + deviceId = deviceId, + homeserverUrl = homeserverUrl, + slidingSyncProxy = slidingSyncProxy, +) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index 71e6e730e5..ba06891013 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -16,33 +16,27 @@ package io.element.android.libraries.matrix.impl.auth -import android.content.Context +// TODO Oidc +// import org.matrix.rustcomponents.sdk.OidcAuthenticationUrl import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.extensions.mapFailure import io.element.android.libraries.di.AppScope -import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.SingleIn import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.OidcDetails import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.matrix.impl.RustMatrixClient +import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.exception.mapClientException import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionData import io.element.android.libraries.sessionstorage.api.SessionStore -import io.element.android.services.toolbox.api.systemclock.SystemClock -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext -import org.matrix.rustcomponents.sdk.Client -import org.matrix.rustcomponents.sdk.ClientBuilder -// TODO Oidc -// import org.matrix.rustcomponents.sdk.OidcAuthenticationUrl import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.use import java.io.File @@ -53,13 +47,11 @@ import org.matrix.rustcomponents.sdk.AuthenticationService as RustAuthentication @ContributesBinding(AppScope::class) @SingleIn(AppScope::class) class RustMatrixAuthenticationService @Inject constructor( - @ApplicationContext private val context: Context, - private val baseDirectory: File, - private val appCoroutineScope: CoroutineScope, + baseDirectory: File, private val coroutineDispatchers: CoroutineDispatchers, private val sessionStore: SessionStore, - private val clock: SystemClock, - private val userAgentProvider: UserAgentProvider, + userAgentProvider: UserAgentProvider, + private val rustMatrixClientFactory: RustMatrixClientFactory, ) : MatrixAuthenticationService { private val authService: RustAuthenticationService = RustAuthenticationService( @@ -84,14 +76,7 @@ class RustMatrixAuthenticationService @Inject constructor( runCatching { val sessionData = sessionStore.getSession(sessionId.value) if (sessionData != null) { - val client = ClientBuilder() - .basePath(baseDirectory.absolutePath) - .homeserverUrl(sessionData.homeserverUrl) - .username(sessionData.userId) - .userAgent(userAgentProvider.provide()) - .use { it.build() } - client.restoreSession(sessionData.toSession()) - createMatrixClient(client) + rustMatrixClientFactory.create(sessionData) } else { error("No session to restore with id $sessionId") } @@ -181,30 +166,8 @@ class RustMatrixAuthenticationService @Inject constructor( */ } - private suspend fun createMatrixClient(client: Client): MatrixClient { - val syncService = client.syncService().finish() - return RustMatrixClient( - client = client, - syncService = syncService, - sessionStore = sessionStore, - appCoroutineScope = appCoroutineScope, - dispatchers = coroutineDispatchers, - baseDirectory = baseDirectory, - baseCacheDirectory = context.cacheDir, - clock = clock, - ) - } } -private fun SessionData.toSession() = Session( - accessToken = accessToken, - refreshToken = refreshToken, - userId = userId, - deviceId = deviceId, - homeserverUrl = homeserverUrl, - slidingSyncProxy = slidingSyncProxy, -) - private fun Session.toSessionData() = SessionData( userId = userId, deviceId = deviceId, diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index 21d6648a41..a915e70046 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -26,11 +26,12 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.core.view.WindowCompat -import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService import io.element.android.libraries.network.useragent.SimpleUserAgentProvider import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.theme.ElementTheme import io.element.android.services.toolbox.impl.systemclock.DefaultSystemClock import kotlinx.coroutines.runBlocking import java.io.File @@ -39,15 +40,22 @@ class MainActivity : ComponentActivity() { private val matrixAuthenticationService: MatrixAuthenticationService by lazy { val baseDirectory = File(applicationContext.filesDir, "sessions") - + val userAgentProvider = SimpleUserAgentProvider("MinimalSample") + val sessionStore = InMemorySessionStore() RustMatrixAuthenticationService( - context = applicationContext, baseDirectory = baseDirectory, - appCoroutineScope = Singleton.appScope, coroutineDispatchers = Singleton.coroutineDispatchers, - sessionStore = InMemorySessionStore(), - clock = DefaultSystemClock(), - userAgentProvider = SimpleUserAgentProvider("MinimalSample") + sessionStore = sessionStore, + userAgentProvider = userAgentProvider, + rustMatrixClientFactory = RustMatrixClientFactory( + context = applicationContext, + baseDirectory = baseDirectory, + appCoroutineScope = Singleton.appScope, + coroutineDispatchers = Singleton.coroutineDispatchers, + sessionStore = sessionStore, + userAgentProvider = userAgentProvider, + clock = DefaultSystemClock() + ) ) }