From 3f19100427cc44fa321dded35d9afdb768acc70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 10 Aug 2026 14:19:41 +0200 Subject: [PATCH] Add `TemporaryMatrixClient` interface This is an abstraction over an actual unauthenticated `Client` from the SDK that implements `GetUrlResolver`, and is supposed to be short-lived. With this, we can use the SDK network stack to perform arbitrary GET url operations. The `AutoCloseable` implementation makes it easier to clean up any leftover local config after using this temporary client. --- .../matrix/api/TemporaryMatrixClient.kt | 18 ++++++++++ .../api/TemporaryMatrixClientFactory.kt | 15 ++++++++ .../matrix/impl/RustTemporaryMatrixClient.kt | 36 +++++++++++++++++++ .../impl/RustTemporaryMatrixClientFactory.kt | 36 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClient.kt create mode 100644 libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClientFactory.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClient.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClientFactory.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClient.kt new file mode 100644 index 0000000000..918b6237a0 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClient.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2026 Element Creations 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.api + +import java.lang.AutoCloseable + +/** + * A Matrix client in an 'unauthenticated' state that can still be used to resolve URLs. + * + * Note: this client implements an [AutoCloseable] interface, so using [AutoCloseable.close] or [AutoCloseable.use] will clean up any resources associated + * with it, such as temporary files. + */ +interface TemporaryMatrixClient : GetUrlResolver, AutoCloseable diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClientFactory.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClientFactory.kt new file mode 100644 index 0000000000..605401af85 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/TemporaryMatrixClientFactory.kt @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026 Element Creations 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.api + +/** + * Factory to create a temporary [TemporaryMatrixClient] for a given home server URL. + */ +interface TemporaryMatrixClientFactory { + suspend fun createTemporaryMatrixClient(homeServerUrl: String): Result +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClient.kt new file mode 100644 index 0000000000..54e4f696d3 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClient.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026 Element Creations 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 + +import io.element.android.libraries.core.extensions.mapFailure +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.TemporaryMatrixClient +import io.element.android.libraries.matrix.api.paths.SessionPaths +import io.element.android.libraries.matrix.impl.exception.mapClientException +import org.matrix.rustcomponents.sdk.Client + +class RustTemporaryMatrixClient( + private val client: Client, + private val paths: SessionPaths?, +) : TemporaryMatrixClient { + override suspend fun getUrl(url: String): Result = runCatchingExceptions { + client.getUrl(url) + }.mapFailure { it.mapClientException() } + + override fun close() { + client.close() + paths?.let { + if (it.fileDirectory.exists()) { + it.fileDirectory.deleteRecursively() + } + if (it.cacheDirectory.exists()) { + it.cacheDirectory.deleteRecursively() + } + } + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClientFactory.kt new file mode 100644 index 0000000000..e2a55c2b8c --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustTemporaryMatrixClientFactory.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2026 Element Creations 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 + +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.matrix.api.TemporaryMatrixClientFactory +import io.element.android.libraries.matrix.api.TemporaryMatrixClient +import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory + +@ContributesBinding(AppScope::class) +class RustTemporaryMatrixClientFactory( + private val sessionPathsFactory: SessionPathsFactory, + private val rustMatrixClientFactory: RustMatrixClientFactory, +) : TemporaryMatrixClientFactory { + override suspend fun createTemporaryMatrixClient(homeServerUrl: String): Result { + return runCatchingExceptions { + val sessionPaths = sessionPathsFactory.create() + val client = rustMatrixClientFactory.getBaseClientBuilder( + sessionPaths = sessionPaths, + clientSecret = null, + slidingSyncType = ClientBuilderSlidingSync.Native, + isMessageSearchAvailable = false, + ) + .homeserverUrl(homeServerUrl) + .build() + RustTemporaryMatrixClient(client, sessionPaths) + } + } +}