From 05fe689bc6d675422116c76f6804aa1772ecad28 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Oct 2025 10:22:47 +0200 Subject: [PATCH 01/27] version++ --- matrix-sdk-android/build.gradle | 2 +- vector-app/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 0b7b2015ffd..70109c63c0f 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -62,7 +62,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.6.48\"" + buildConfigField "String", "SDK_VERSION", "\"1.6.50\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector-app/build.gradle b/vector-app/build.gradle index e4f9a5b15ac..1905e397f5f 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 48 +ext.versionPatch = 50 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From 703891473ad4db51c47fd8893daf4227f1110fe4 Mon Sep 17 00:00:00 2001 From: Ben Banfield-Zanin Date: Thu, 6 Nov 2025 10:28:52 +0000 Subject: [PATCH 02/27] Use the dedicated subdomain for the bug report URL by default Signed-off-by: Ben Banfield-Zanin --- changelog.d/9097.misc | 1 + vector-config/src/main/res/values/config.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/9097.misc diff --git a/changelog.d/9097.misc b/changelog.d/9097.misc new file mode 100644 index 00000000000..7a20e030876 --- /dev/null +++ b/changelog.d/9097.misc @@ -0,0 +1 @@ +Update the default bug reporting URL. diff --git a/vector-config/src/main/res/values/config.xml b/vector-config/src/main/res/values/config.xml index cae094f4547..6ab8892fc9d 100755 --- a/vector-config/src/main/res/values/config.xml +++ b/vector-config/src/main/res/values/config.xml @@ -7,7 +7,7 @@ https://matrix.org - https://riot.im/bugreports/submit + https://rageshakes.element.io/api/submit riot-android element-auto-uisi From c1ed75b07f8ae3297777e5f194c1e1c3131a9bee Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 15 Dec 2025 19:12:59 +0000 Subject: [PATCH 03/27] Support for stable version of MSC3824 OAuth 2.0 aware --- .../matrix/android/sdk/api/auth/SSOAction.kt | 6 +-- .../android/sdk/api/auth/data/AuthMetadata.kt | 49 +++++++++++++++++++ .../homeserver/HomeServerCapabilities.kt | 33 ++++++++++++- .../auth/DefaultAuthenticationService.kt | 10 ++-- .../internal/auth/data/LoginFlowResponse.kt | 18 +++++-- .../mapper/HomeServerCapabilitiesMapper.kt | 1 + .../model/HomeServerCapabilitiesEntity.kt | 1 + .../session/homeserver/AuthMetadataAPI.kt | 30 ++++++++++++ .../session/homeserver/AuthMetadataModule.kt | 41 ++++++++++++++++ .../GetHomeServerCapabilitiesTask.kt | 27 ++++++++-- .../HomeServerCapabilitiesModule.kt | 7 +++ .../settings/devices/DevicesViewModel.kt | 6 +-- .../v2/overview/SessionOverviewFragment.kt | 4 +- .../v2/overview/SessionOverviewViewModel.kt | 8 +-- .../v2/overview/SessionOverviewViewState.kt | 2 +- .../fixtures/HomeserverCapabilityFixture.kt | 2 + 16 files changed, 221 insertions(+), 24 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/SSOAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/SSOAction.kt index db2dd870d52..bd5dfb662cc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/SSOAction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/SSOAction.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.api.auth /** * See https://github.com/matrix-org/matrix-spec-proposals/pull/3824 */ -enum class SSOAction { - LOGIN, - REGISTER; +enum class SSOAction(val value: String) { + LOGIN("login"), + REGISTER("register"); } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt new file mode 100644 index 00000000000..80a7066671b --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2023 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.auth.data + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.extensions.orFalse + +/** + * This is a subset of the server metadata discovery for the OAuth 2.0 API + * https://spec.matrix.org/v1.16/client-server-api/#get_matrixclientv1auth_metadata + * + * Includes the values from MSC4191: https://github.com/matrix-org/matrix-spec-proposals/pull/4191 + * + *
+ * {
+ *     "issuer": "https://id.server.org",
+ *     "account_management_uri": "https://id.server.org/my-account",
+ *     "account_management_actions_supported": ["org.matrix.profile", "org.matrix.devices_list"],
+ * }
+ * 
+ * . + */ + +@JsonClass(generateAdapter = true) +data class AuthMetadata( + @Json(name = "issuer") + val issuer: String, + + @Json(name = "account_management_uri") + val accountManagementUri: String?, + + @Json(name = "account_management_actions_supported") + val accountManagementActionsSupported: List?, +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 101947f9d9b..4536b527fb2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.api.session.homeserver +import org.matrix.android.sdk.api.extensions.orFalse + data class HomeServerCapabilities( /** * True if it is possible to change the password of the account. @@ -82,12 +84,17 @@ data class HomeServerCapabilities( var canRedactRelatedEvents: Boolean = false, /** - * External account management url for use with MSC3824 delegated OIDC, provided in Wellknown. + * External account management url for use with OAuth API, provided by MSC4191 /auth_metadata discovery or in unstable Wellknown. */ val externalAccountManagementUrl: String? = null, /** - * Authentication issuer for use with MSC3824 delegated OIDC, provided in Wellknown. + * External account management supported actions for use with OAuth API, provided by MSC4191 /auth_metadata discovery + */ + val externalAccountManagementSupportedActions: List? = null, + + /** + * Authentication issuer for use with MSC3824 delegated OIDC, provided by /auth_metadata discovery or in unstable Wellknown. */ val authenticationIssuer: String? = null, @@ -162,4 +169,26 @@ data class HomeServerCapabilities( const val ROOM_CAP_KNOCK = "knock" const val ROOM_CAP_RESTRICTED = "restricted" } + + fun getLogoutDeviceURL(deviceId: String): String? { + if (externalAccountManagementUrl == null) { + return null; + } + + // default to the stable value: + var action = "org.matrix.device_delete" + externalAccountManagementSupportedActions?.also { actions -> + if (actions.contains("org.matrix.device_delete")) { + // server supports stable version so use it + } else if (actions.contains("org.matrix.session_end")) { + // earlier version of MSC4191: + action = "org.matrix.session_end" + } else if (actions.contains("session_end")) { + // previous unspecified version + action = "session_end" + } + } + + return externalAccountManagementUrl.removeSuffix("/") + "?action=${action}&device_id=${deviceId}" + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt index e852c61185b..6b9a06a6046 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultAuthenticationService.kt @@ -106,7 +106,11 @@ internal class DefaultAuthenticationService @Inject constructor( } // unstable MSC3824 action param - appendParamToUrl("org.matrix.msc3824.action", action.toString()) + // This can be removed once servers have been updated to support the stable one. + appendParamToUrl("org.matrix.msc3824.action", action.value) + + // stable param: + appendParamToUrl("action", action.value) } } @@ -297,8 +301,8 @@ internal class DefaultAuthenticationService @Inject constructor( authAPI.getLoginFlows() } - // If an m.login.sso flow is present that is flagged as being for MSC3824 OIDC compatibility then we only return that flow - val oidcCompatibilityFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.sso" && it.delegatedOidcCompatibility == true } + // If an m.login.sso flow is present that is flagged as being for MSC3824 OAuth compatibility then we only return that flow + val oidcCompatibilityFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.sso" && it.delegatedOidcCompatibility } val flows = if (oidcCompatibilityFlow != null) listOf(oidcCompatibilityFlow) else loginFlowResponse.flows val supportsGetLoginTokenFlow = loginFlowResponse.flows.orEmpty().firstOrNull { it.type == "m.login.token" && it.getLoginToken == true } != null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt index 2e52740ed48..35972d98933 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.auth.data import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider +import org.matrix.android.sdk.api.extensions.orFalse @JsonClass(generateAdapter = true) internal data class LoginFlowResponse( @@ -46,12 +47,20 @@ internal data class LoginFlow( val ssoIdentityProvider: List? = null, /** - * Whether this login flow is preferred for OIDC-aware clients. + * Whether this login flow is preferred for OAuth 2.0-aware clients like we are. * * See [MSC3824](https://github.com/matrix-org/matrix-spec-proposals/pull/3824) */ + @Json(name = "oauth_aware_preferred") + val oauthAwarePreferred: Boolean? = null, + + /** + * Unstable name from MSC3824. + * + * @deprecated Use {@link oauthAwarePreferred} instead. + */ @Json(name = "org.matrix.msc3824.delegated_oidc_compatibility") - val delegatedOidcCompatibility: Boolean? = null, + val unstableDelegatedOidcCompatibility: Boolean? = null, /** * Whether a login flow of type m.login.token could accept a token issued using /login/get_token. @@ -60,4 +69,7 @@ internal data class LoginFlow( */ @Json(name = "get_login_token") val getLoginToken: Boolean? = null -) +) { + val delegatedOidcCompatibility: Boolean + get() = this.oauthAwarePreferred.orFalse() || this.unstableDelegatedOidcCompatibility.orFalse() +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt index 8cdabaf1504..1c6ba850d74 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt @@ -49,6 +49,7 @@ internal object HomeServerCapabilitiesMapper { canRemotelyTogglePushNotificationsOfDevices = entity.canRemotelyTogglePushNotificationsOfDevices, canRedactRelatedEvents = entity.canRedactEventWithRelations, externalAccountManagementUrl = entity.externalAccountManagementUrl, + externalAccountManagementSupportedActions = entity.externalAccountManagementSupportedActions?.split(","), authenticationIssuer = entity.authenticationIssuer, disableNetworkConstraint = entity.disableNetworkConstraint, canUseAuthenticatedMedia = entity.canUseAuthenticatedMedia, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt index 0096071d547..d77d9025953 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt @@ -36,6 +36,7 @@ internal open class HomeServerCapabilitiesEntity( var canRemotelyTogglePushNotificationsOfDevices: Boolean = false, var canRedactEventWithRelations: Boolean = false, var externalAccountManagementUrl: String? = null, + var externalAccountManagementSupportedActions: String? = null, var authenticationIssuer: String? = null, var disableNetworkConstraint: Boolean? = null, var canUseAuthenticatedMedia: Boolean = false, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt new file mode 100644 index 00000000000..9a12cbc2166 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2025 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.session.homeserver + +import org.matrix.android.sdk.api.auth.data.AuthMetadata +import org.matrix.android.sdk.internal.auth.version.Versions +import org.matrix.android.sdk.internal.network.NetworkConstants +import retrofit2.http.GET + +internal interface AuthMetadataAPI { + /** + * Request the homeserver OAuth 2.0 auth metadata. + */ + @GET(NetworkConstants.URI_API_PREFIX_PATH_V1 + "auth_metadata") + suspend fun getAuthMetadata(): AuthMetadata +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt new file mode 100644 index 00000000000..a3efe04a141 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.session.homeserver + +import dagger.Binds +import dagger.Module +import dagger.Provides +import org.matrix.android.sdk.internal.session.SessionScope +import org.matrix.android.sdk.internal.wellknown.WellknownModule +import retrofit2.Retrofit + +@Module(includes = [WellknownModule::class]) +internal abstract class AuthMetadataModule { + + @Module + companion object { + @Provides + @JvmStatic + @SessionScope + fun providesAuthMetadataAPI(retrofit: Retrofit): AuthMetadataAPI { + return retrofit.create(AuthMetadataAPI::class.java) + } + } + + @Binds + abstract fun bindGetHomeServerCapabilitiesTask(task: DefaultGetHomeServerCapabilitiesTask): GetHomeServerCapabilitiesTask +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 5314237c3c2..e82aa71fa8f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.homeserver import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.MatrixPatterns.getServerName +import org.matrix.android.sdk.api.auth.data.AuthMetadata import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.wellknown.WellknownResult import org.matrix.android.sdk.api.extensions.orFalse @@ -66,7 +67,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( private val configExtractor: IntegrationManagerConfigExtractor, private val homeServerConnectionConfig: HomeServerConnectionConfig, @UserId - private val userId: String + private val userId: String, + private val authMetadataAPI: AuthMetadataAPI, ) : GetHomeServerCapabilitiesTask { override suspend fun execute(params: GetHomeServerCapabilitiesTask.Params) { @@ -104,6 +106,12 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( } }.getOrNull() + val authMetadata = runCatching { + executeRequest(globalErrorReceiver = null) { + authMetadataAPI.getAuthMetadata() + } + }.getOrNull(); + // Domain may include a port (eg, matrix.org:8080) // Per https://spec.matrix.org/latest/client-server-api/#well-known-uri we should extract the hostname from the server name // So we take everything before the last : as the domain for the well-known task. @@ -117,14 +125,15 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( ) }.getOrNull() - insertInDb(capabilities, mediaConfig, versions, wellknownResult) + insertInDb(capabilities, mediaConfig, versions, wellknownResult, authMetadata) } private suspend fun insertInDb( getCapabilitiesResult: GetCapabilitiesResult?, getMediaConfigResult: GetMediaConfigResult?, getVersionResult: Versions?, - getWellknownResult: WellknownResult? + getWellknownResult: WellknownResult?, + authMetadata: AuthMetadata?, ) { monarchy.awaitTransaction { realm -> val homeServerCapabilitiesEntity = HomeServerCapabilitiesEntity.getOrCreate(realm) @@ -174,11 +183,23 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( Timber.v("Extracted integration config : $config") realm.insertOrUpdate(config) } + // Getting the OAuth 2.0 metadata from well-known was in unstable MSC: homeServerCapabilitiesEntity.authenticationIssuer = getWellknownResult.wellKnown.unstableDelegatedAuthConfig?.issuer homeServerCapabilitiesEntity.externalAccountManagementUrl = getWellknownResult.wellKnown.unstableDelegatedAuthConfig?.accountManagementUrl homeServerCapabilitiesEntity.disableNetworkConstraint = getWellknownResult.wellKnown.disableNetworkConstraint } + // If the server returns OAuth 2.0 metadata then prefer that over the well-known values: + if (authMetadata != null) { + homeServerCapabilitiesEntity.authenticationIssuer = authMetadata.issuer; + if (authMetadata.accountManagementUri != null) { + homeServerCapabilitiesEntity.externalAccountManagementUrl = authMetadata.accountManagementUri; + } + if (authMetadata.accountManagementActionsSupported != null) { + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions = authMetadata.accountManagementActionsSupported.joinToString(",") + } + } + homeServerCapabilitiesEntity.canLoginWithQrCode = canLoginWithQrCode(getCapabilitiesResult, getVersionResult) homeServerCapabilitiesEntity.lastUpdatedTimestamp = Date().time diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesModule.kt index 2a1573dd98f..88988addcea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/HomeServerCapabilitiesModule.kt @@ -34,6 +34,13 @@ internal abstract class HomeServerCapabilitiesModule { fun providesCapabilitiesAPI(retrofit: Retrofit): CapabilitiesAPI { return retrofit.create(CapabilitiesAPI::class.java) } + + @Provides + @JvmStatic + @SessionScope + fun providesAuthMetadataAPI(retrofit: Retrofit): AuthMetadataAPI { + return retrofit.create(AuthMetadataAPI::class.java) + } } @Binds diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 1c9fb718585..0282bf9a73b 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -337,12 +337,12 @@ class DevicesViewModel @AssistedInject constructor( private fun handleDelete(action: DevicesAction.Delete) { val deviceId = action.deviceId - val accountManagementUrl = session.homeServerCapabilitiesService().getHomeServerCapabilities().externalAccountManagementUrl - if (accountManagementUrl != null) { + val externalLogoutDeviceUrl = session.homeServerCapabilitiesService().getHomeServerCapabilities().getLogoutDeviceURL(deviceId); + if (externalLogoutDeviceUrl != null) { // Open external browser to delete this session _viewEvents.post( DevicesViewEvents.OpenBrowser( - url = accountManagementUrl.removeSuffix("/") + "?action=session_end&device_id=$deviceId" + url = externalLogoutDeviceUrl ) ) } else { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt index 0d90f4f2c98..56a13a77c0f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewFragment.kt @@ -129,12 +129,12 @@ class SessionOverviewFragment : } private fun confirmSignoutOtherSession() = withState(viewModel) { state -> - if (state.externalAccountManagementUrl != null) { + if (state.externalDeleteDeviceUrl != null) { // Manage in external account manager openUrlInChromeCustomTab( requireContext(), null, - state.externalAccountManagementUrl.removeSuffix("/") + "?action=session_end&device_id=${state.deviceId}" + state.externalDeleteDeviceUrl, ) } else { activity?.let { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt index 8a34f6ce6ed..54cdde22e15 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt @@ -66,16 +66,16 @@ class SessionOverviewViewModel @AssistedInject constructor( observeNotificationsStatus(initialState.deviceId) refreshIpAddressVisibility() observePreferences() - initExternalAccountManagementUrl() + initExternalDeleteDeviceUrl() } - private fun initExternalAccountManagementUrl() { + private fun initExternalDeleteDeviceUrl() { setState { copy( - externalAccountManagementUrl = activeSessionHolder.getSafeActiveSession() + externalDeleteDeviceUrl = activeSessionHolder.getSafeActiveSession() ?.homeServerCapabilitiesService() ?.getHomeServerCapabilities() - ?.externalAccountManagementUrl + ?.getLogoutDeviceURL(deviceId) ) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt index f795d29969f..da1847a397b 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewState.kt @@ -20,7 +20,7 @@ data class SessionOverviewViewState( val isLoading: Boolean = false, val notificationsStatus: NotificationsStatus = NotificationsStatus.NOT_SUPPORTED, val isShowingIpAddress: Boolean = false, - val externalAccountManagementUrl: String? = null, + val externalDeleteDeviceUrl: String? = null, ) : MavericksState { constructor(args: SessionOverviewArgs) : this( deviceId = args.deviceId diff --git a/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt index a66fc201c70..ff30a37895f 100644 --- a/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt +++ b/vector/src/test/java/im/vector/app/test/fixtures/HomeserverCapabilityFixture.kt @@ -21,6 +21,7 @@ fun aHomeServerCapabilities( roomVersions: RoomVersionCapabilities? = null, canRemotelyTogglePushNotificationsOfDevices: Boolean = true, externalAccountManagementUrl: String? = null, + externalAccountManagementSupportedActions: List? = null, ) = HomeServerCapabilities( canChangePassword = canChangePassword, canChangeDisplayName = canChangeDisplayName, @@ -32,4 +33,5 @@ fun aHomeServerCapabilities( roomVersions = roomVersions, canRemotelyTogglePushNotificationsOfDevices = canRemotelyTogglePushNotificationsOfDevices, externalAccountManagementUrl = externalAccountManagementUrl, + externalAccountManagementSupportedActions = externalAccountManagementSupportedActions, ) From e68101c118bbe2b1afbc5110bf3f1bf4ee838d4b Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 19 Dec 2025 11:11:03 +0000 Subject: [PATCH 04/27] Use all values from auth metadata even if null --- .../session/homeserver/GetHomeServerCapabilitiesTask.kt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index e82aa71fa8f..00de4b986d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -192,12 +192,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( // If the server returns OAuth 2.0 metadata then prefer that over the well-known values: if (authMetadata != null) { homeServerCapabilitiesEntity.authenticationIssuer = authMetadata.issuer; - if (authMetadata.accountManagementUri != null) { - homeServerCapabilitiesEntity.externalAccountManagementUrl = authMetadata.accountManagementUri; - } - if (authMetadata.accountManagementActionsSupported != null) { - homeServerCapabilitiesEntity.externalAccountManagementSupportedActions = authMetadata.accountManagementActionsSupported.joinToString(",") - } + homeServerCapabilitiesEntity.externalAccountManagementUrl = authMetadata.accountManagementUri; + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions = if (authMetadata.accountManagementActionsSupported != null) authMetadata.accountManagementActionsSupported.joinToString(",") else null } homeServerCapabilitiesEntity.canLoginWithQrCode = canLoginWithQrCode(getCapabilitiesResult, getVersionResult) From a3684fa2439008cadb34ad26c58e58dbe6d7450a Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 19 Dec 2025 11:11:08 +0000 Subject: [PATCH 05/27] Test cases --- .../homeserver/HomeServerCapabilitiesTest.kt | 83 +++++++++ ...efaultGetHomeServerCapabilitiesTaskTest.kt | 166 ++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt create mode 100644 matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt new file mode 100644 index 00000000000..9bb1f1df841 --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2025 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.session.homeserver + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test + +class HomeServerCapabilitiesTest { + + private val deviceId = "TEST_DEVICE_ID" + + @Test + fun `given externalAccountManagementUrl is null, when getLogoutDeviceURL, then return null`() { + val capabilities = HomeServerCapabilities( + externalAccountManagementUrl = null + ) + assertNull(capabilities.getLogoutDeviceURL(deviceId)) + } + + @Test + fun `given supported actions is null, when getLogoutDeviceURL, then uses default stable action`() { + val capabilities = HomeServerCapabilities( + externalAccountManagementUrl = "https://example.com", + externalAccountManagementSupportedActions = null + ) + val expectedUrl = "https://example.com?action=org.matrix.device_delete&device_id=$deviceId" + assertEquals(expectedUrl, capabilities.getLogoutDeviceURL(deviceId)) + } + + @Test + fun `given supported actions contains stable action, when getLogoutDeviceURL, then uses stable action`() { + val capabilities = HomeServerCapabilities( + externalAccountManagementUrl = "https://example.com", + externalAccountManagementSupportedActions = listOf("org.matrix.device_delete", "org.matrix.session_end", "session_end") + ) + val expectedUrl = "https://example.com?action=org.matrix.device_delete&device_id=$deviceId" + assertEquals(expectedUrl, capabilities.getLogoutDeviceURL(deviceId)) + } + + @Test + fun `given supported actions contains unstable action, when getLogoutDeviceURL, then uses unstable action`() { + val capabilities = HomeServerCapabilities( + externalAccountManagementUrl = "https://example.com", + externalAccountManagementSupportedActions = listOf("org.matrix.session_end", "session_end") + ) + val expectedUrl = "https://example.com?action=org.matrix.session_end&device_id=$deviceId" + assertEquals(expectedUrl, capabilities.getLogoutDeviceURL(deviceId)) + } + + @Test + fun `given supported actions contains legacy action, when getLogoutDeviceURL, then uses legacy action`() { + val capabilities = HomeServerCapabilities( + externalAccountManagementUrl = "https://example.com", + externalAccountManagementSupportedActions = listOf("session_end") + ) + val expectedUrl = "https://example.com?action=session_end&device_id=$deviceId" + assertEquals(expectedUrl, capabilities.getLogoutDeviceURL(deviceId)) + } + + @Test + fun `given url with trailing slash, when getLogoutDeviceURL, then slash is removed`() { + val capabilities = HomeServerCapabilities( + externalAccountManagementUrl = "https://example.com/account/" + ) + val expectedUrl = "https://example.com/account?action=org.matrix.device_delete&device_id=$deviceId" + assertEquals(expectedUrl, capabilities.getLogoutDeviceURL(deviceId)) + } +} diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt new file mode 100644 index 00000000000..7ce6758a2c5 --- /dev/null +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt @@ -0,0 +1,166 @@ +/* + * Copyright 2025 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.session.homeserver + +import io.mockk.coEvery +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.shouldBeEqualTo +import org.junit.Before +import org.junit.Test +import org.matrix.android.sdk.api.auth.data.AuthMetadata +import org.matrix.android.sdk.api.auth.data.DelegatedAuthConfig +import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig +import org.matrix.android.sdk.api.auth.data.WellKnown +import org.matrix.android.sdk.api.auth.wellknown.WellknownResult +import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntity +import org.matrix.android.sdk.internal.network.GlobalErrorReceiver +import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationManagerConfigExtractor +import org.matrix.android.sdk.internal.session.media.AuthenticatedMediaAPI +import org.matrix.android.sdk.internal.session.media.UnauthenticatedMediaAPI +import org.matrix.android.sdk.internal.wellknown.GetWellknownTask +import org.matrix.android.sdk.test.fakes.FakeMonarchy + +class DefaultGetHomeServerCapabilitiesTaskTest { + + private val capabilitiesAPI: CapabilitiesAPI = mockk() + private val unauthenticatedMediaAPI: UnauthenticatedMediaAPI = mockk() + private val authenticatedMediaAPI: AuthenticatedMediaAPI = mockk() + private val monarchy = FakeMonarchy() + private val globalErrorReceiver: GlobalErrorReceiver = mockk(relaxed = true) + private val getWellknownTask: GetWellknownTask = mockk() + private val configExtractor: IntegrationManagerConfigExtractor = mockk() + private val homeServerConnectionConfig: HomeServerConnectionConfig = mockk() + private val authMetadataAPI: AuthMetadataAPI = mockk() + + private val task = DefaultGetHomeServerCapabilitiesTask( + capabilitiesAPI, + unauthenticatedMediaAPI, + authenticatedMediaAPI, + monarchy.instance, + globalErrorReceiver, + getWellknownTask, + configExtractor, + homeServerConnectionConfig, + "userId", + authMetadataAPI + ) + + private val homeServerCapabilitiesEntity = HomeServerCapabilitiesEntity() + + @Before + fun setUp() { + coEvery { configExtractor.extract(any())} returns null + monarchy.givenWhereReturns(result = homeServerCapabilitiesEntity) + } + + private val wellKnownWithoutDelegation = WellknownResult.Prompt( + homeServerUrl = "https://test", + identityServerUrl = null, + wellKnown = WellKnown( + homeServer = mockk(), + identityServer = mockk(), + unstableDelegatedAuthConfig = null, + ) + ) + + private val wellKnownWithDelegationToTest1 = WellknownResult.Prompt( + homeServerUrl = "https://test", + identityServerUrl = null, + wellKnown = WellKnown( + homeServer = mockk(), + identityServer = mockk(), + unstableDelegatedAuthConfig = DelegatedAuthConfig( + issuer = "https://test1", + accountManagementUrl = "https://test1/account" + ) + ) + ) + + private val authMetadataForTest2 = AuthMetadata( + issuer = "https://test2", + accountManagementUri = "https://test2/account", + accountManagementActionsSupported = listOf("org.matrix.device_delete", "org.matrix.profile") + ) + + private val authMetadataForTest2WithoutAccountManagement = AuthMetadata( + issuer = "https://test2", + accountManagementUri = null, + accountManagementActionsSupported = null + ) + + @Test + fun `given no OAuth config, when execute, then fields are null`() = runTest { + // Given + coEvery { getWellknownTask.execute(any()) } throws Exception() + coEvery { authMetadataAPI.getAuthMetadata() } throws Exception() + + // When + task.execute(GetHomeServerCapabilitiesTask.Params(forceRefresh = false)) + + // Then + homeServerCapabilitiesEntity.authenticationIssuer shouldBeEqualTo null + homeServerCapabilitiesEntity.externalAccountManagementUrl shouldBeEqualTo null + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions shouldBeEqualTo null + } + + @Test + fun `given well-known, when execute, populates fields`() = runTest { + // Given + coEvery { getWellknownTask.execute(any()) } returns wellKnownWithDelegationToTest1 + coEvery { authMetadataAPI.getAuthMetadata() } throws Exception() + + // When + task.execute(GetHomeServerCapabilitiesTask.Params(forceRefresh = false)) + + // Then + homeServerCapabilitiesEntity.authenticationIssuer shouldBeEqualTo "https://test1" + homeServerCapabilitiesEntity.externalAccountManagementUrl shouldBeEqualTo "https://test1/account" + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions shouldBeEqualTo null + } + + @Test + fun `given auth metadata, when execute, populates fields`() = runTest { + // Given + coEvery { getWellknownTask.execute(any()) } returns wellKnownWithoutDelegation + coEvery { authMetadataAPI.getAuthMetadata() } returns authMetadataForTest2 + + + // When + task.execute(GetHomeServerCapabilitiesTask.Params(forceRefresh = false)) + + // Then + homeServerCapabilitiesEntity.authenticationIssuer shouldBeEqualTo "https://test2" + homeServerCapabilitiesEntity.externalAccountManagementUrl shouldBeEqualTo "https://test2/account" + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions shouldBeEqualTo "org.matrix.device_delete,org.matrix.profile" + } + + @Test + fun `given well-known and auth metadata, when execute, treats auth metadata as authoritative`() = runTest { + // Given + coEvery { getWellknownTask.execute(any()) } returns wellKnownWithDelegationToTest1 + coEvery { authMetadataAPI.getAuthMetadata() } returns authMetadataForTest2WithoutAccountManagement + + // When + task.execute(GetHomeServerCapabilitiesTask.Params(forceRefresh = false)) + + // Then + homeServerCapabilitiesEntity.authenticationIssuer shouldBeEqualTo "https://test2" + homeServerCapabilitiesEntity.externalAccountManagementUrl shouldBeEqualTo null + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions shouldBeEqualTo null + } +} From 5117c9363952be63069c24f3677e2155405c8dc0 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 19 Dec 2025 11:15:55 +0000 Subject: [PATCH 06/27] Changelog --- changelog.d/9102.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/9102.misc diff --git a/changelog.d/9102.misc b/changelog.d/9102.misc new file mode 100644 index 00000000000..705a7a57fbd --- /dev/null +++ b/changelog.d/9102.misc @@ -0,0 +1 @@ +Update OAuth-awareness to support the stable version of MSC3824. From 4d46daf0d266d62b4134103cefd81e9b1c5cb625 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 19 Dec 2025 11:40:42 +0000 Subject: [PATCH 07/27] Lint --- .../org/matrix/android/sdk/api/auth/data/AuthMetadata.kt | 1 - .../sdk/api/session/homeserver/HomeServerCapabilities.kt | 4 +--- .../sdk/internal/session/homeserver/AuthMetadataAPI.kt | 1 - .../session/homeserver/GetHomeServerCapabilitiesTask.kt | 6 +++--- .../homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt | 3 +-- .../app/features/settings/devices/DevicesViewModel.kt | 2 +- 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt index 80a7066671b..f78e95c6f1b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.api.auth.data import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.extensions.orFalse /** * This is a subset of the server metadata discovery for the OAuth 2.0 API diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 4536b527fb2..3dae2d4f604 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -16,8 +16,6 @@ package org.matrix.android.sdk.api.session.homeserver -import org.matrix.android.sdk.api.extensions.orFalse - data class HomeServerCapabilities( /** * True if it is possible to change the password of the account. @@ -172,7 +170,7 @@ data class HomeServerCapabilities( fun getLogoutDeviceURL(deviceId: String): String? { if (externalAccountManagementUrl == null) { - return null; + return null } // default to the stable value: diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt index 9a12cbc2166..fbbee8de47e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt @@ -17,7 +17,6 @@ package org.matrix.android.sdk.internal.session.homeserver import org.matrix.android.sdk.api.auth.data.AuthMetadata -import org.matrix.android.sdk.internal.auth.version.Versions import org.matrix.android.sdk.internal.network.NetworkConstants import retrofit2.http.GET diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 00de4b986d8..06895de8acd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -110,7 +110,7 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( executeRequest(globalErrorReceiver = null) { authMetadataAPI.getAuthMetadata() } - }.getOrNull(); + }.getOrNull() // Domain may include a port (eg, matrix.org:8080) // Per https://spec.matrix.org/latest/client-server-api/#well-known-uri we should extract the hostname from the server name @@ -191,8 +191,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( // If the server returns OAuth 2.0 metadata then prefer that over the well-known values: if (authMetadata != null) { - homeServerCapabilitiesEntity.authenticationIssuer = authMetadata.issuer; - homeServerCapabilitiesEntity.externalAccountManagementUrl = authMetadata.accountManagementUri; + homeServerCapabilitiesEntity.authenticationIssuer = authMetadata.issuer + homeServerCapabilitiesEntity.externalAccountManagementUrl = authMetadata.accountManagementUri homeServerCapabilitiesEntity.externalAccountManagementSupportedActions = if (authMetadata.accountManagementActionsSupported != null) authMetadata.accountManagementActionsSupported.joinToString(",") else null } diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt index 7ce6758a2c5..6872786bdd2 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt @@ -64,7 +64,7 @@ class DefaultGetHomeServerCapabilitiesTaskTest { @Before fun setUp() { - coEvery { configExtractor.extract(any())} returns null + coEvery { configExtractor.extract(any()) } returns null monarchy.givenWhereReturns(result = homeServerCapabilitiesEntity) } @@ -139,7 +139,6 @@ class DefaultGetHomeServerCapabilitiesTaskTest { coEvery { getWellknownTask.execute(any()) } returns wellKnownWithoutDelegation coEvery { authMetadataAPI.getAuthMetadata() } returns authMetadataForTest2 - // When task.execute(GetHomeServerCapabilitiesTask.Params(forceRefresh = false)) diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 0282bf9a73b..3ec7cd64aee 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -337,7 +337,7 @@ class DevicesViewModel @AssistedInject constructor( private fun handleDelete(action: DevicesAction.Delete) { val deviceId = action.deviceId - val externalLogoutDeviceUrl = session.homeServerCapabilitiesService().getHomeServerCapabilities().getLogoutDeviceURL(deviceId); + val externalLogoutDeviceUrl = session.homeServerCapabilitiesService().getHomeServerCapabilities().getLogoutDeviceURL(deviceId) if (externalLogoutDeviceUrl != null) { // Open external browser to delete this session _viewEvents.post( From 9af7512537bdadff30bb9fdb92656cff2bfb668a Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Fri, 19 Dec 2025 11:57:10 +0000 Subject: [PATCH 08/27] Lint --- .../sdk/api/session/homeserver/HomeServerCapabilities.kt | 2 +- .../android/sdk/internal/auth/data/LoginFlowResponse.kt | 4 ++-- .../session/homeserver/GetHomeServerCapabilitiesTask.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 3dae2d4f604..5404eecc496 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -87,7 +87,7 @@ data class HomeServerCapabilities( val externalAccountManagementUrl: String? = null, /** - * External account management supported actions for use with OAuth API, provided by MSC4191 /auth_metadata discovery + * External account management supported actions for use with OAuth API, provided by MSC4191 /auth_metadata discovery. */ val externalAccountManagementSupportedActions: List? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt index 35972d98933..6d8d02fabb2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/LoginFlowResponse.kt @@ -57,8 +57,8 @@ internal data class LoginFlow( /** * Unstable name from MSC3824. * - * @deprecated Use {@link oauthAwarePreferred} instead. */ + @Deprecated("Use oauthAwarePreferred instead") @Json(name = "org.matrix.msc3824.delegated_oidc_compatibility") val unstableDelegatedOidcCompatibility: Boolean? = null, @@ -70,6 +70,6 @@ internal data class LoginFlow( @Json(name = "get_login_token") val getLoginToken: Boolean? = null ) { - val delegatedOidcCompatibility: Boolean + @Suppress("DEPRECATION") val delegatedOidcCompatibility: Boolean get() = this.oauthAwarePreferred.orFalse() || this.unstableDelegatedOidcCompatibility.orFalse() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt index 06895de8acd..31d71286c91 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt @@ -193,7 +193,7 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor( if (authMetadata != null) { homeServerCapabilitiesEntity.authenticationIssuer = authMetadata.issuer homeServerCapabilitiesEntity.externalAccountManagementUrl = authMetadata.accountManagementUri - homeServerCapabilitiesEntity.externalAccountManagementSupportedActions = if (authMetadata.accountManagementActionsSupported != null) authMetadata.accountManagementActionsSupported.joinToString(",") else null + homeServerCapabilitiesEntity.externalAccountManagementSupportedActions = authMetadata.accountManagementActionsSupported?.joinToString(",") } homeServerCapabilitiesEntity.canLoginWithQrCode = canLoginWithQrCode(getCapabilitiesResult, getVersionResult) From 04883b20c93c5d92ed41d7ee532ca91ba9c76027 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jan 2026 23:01:13 +0000 Subject: [PATCH 09/27] Bump org.matrix.rustcomponents:crypto-android from 0.11.1 to 26.1.4 Bumps [org.matrix.rustcomponents:crypto-android](https://github.com/matrix-org/matrix-rust-components-kotlin) from 0.11.1 to 26.1.4. - [Release notes](https://github.com/matrix-org/matrix-rust-components-kotlin/releases) - [Commits](https://github.com/matrix-org/matrix-rust-components-kotlin/compare/crypto-v0.11.1...crypto-v26.1.4) --- updated-dependencies: - dependency-name: org.matrix.rustcomponents:crypto-android dependency-version: 26.1.4 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 70109c63c0f..8586e0077b0 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -221,7 +221,7 @@ dependencies { implementation libs.google.phonenumber - implementation("org.matrix.rustcomponents:crypto-android:0.11.1") + implementation("org.matrix.rustcomponents:crypto-android:26.1.4") // api project(":library:rustCrypto") testImplementation libs.tests.junit From 0367786ccfa3ffbfb63cc2fc4f21cfb0c378318b Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 7 Jan 2026 12:19:28 +0000 Subject: [PATCH 10/27] Update matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt Co-authored-by: Benoit Marty --- .../java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt index f78e95c6f1b..62a2382842a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/AuthMetadata.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Matrix.org Foundation C.I.C. + * Copyright 2026 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 88c53c2b559d97000e2a0ce4bbf346621281f511 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 7 Jan 2026 12:39:46 +0000 Subject: [PATCH 11/27] Remove unused file --- .../session/homeserver/AuthMetadataModule.kt | 41 ------------------- 1 file changed, 41 deletions(-) delete mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt deleted file mode 100644 index a3efe04a141..00000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataModule.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2020 The Matrix.org Foundation C.I.C. - * - * 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 org.matrix.android.sdk.internal.session.homeserver - -import dagger.Binds -import dagger.Module -import dagger.Provides -import org.matrix.android.sdk.internal.session.SessionScope -import org.matrix.android.sdk.internal.wellknown.WellknownModule -import retrofit2.Retrofit - -@Module(includes = [WellknownModule::class]) -internal abstract class AuthMetadataModule { - - @Module - companion object { - @Provides - @JvmStatic - @SessionScope - fun providesAuthMetadataAPI(retrofit: Retrofit): AuthMetadataAPI { - return retrofit.create(AuthMetadataAPI::class.java) - } - } - - @Binds - abstract fun bindGetHomeServerCapabilitiesTask(task: DefaultGetHomeServerCapabilitiesTask): GetHomeServerCapabilitiesTask -} From df2bf39d4d9e4544b3c59c293e00ea7de2d32fcc Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 7 Jan 2026 17:22:20 +0000 Subject: [PATCH 12/27] Be consistent with copyright year --- .../android/sdk/internal/session/homeserver/AuthMetadataAPI.kt | 2 +- .../sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt | 2 +- .../homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt index fbbee8de47e..cf6cab289dc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/AuthMetadataAPI.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Matrix.org Foundation C.I.C. + * Copyright 2026 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt index 9bb1f1df841..75a828fccec 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilitiesTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Matrix.org Foundation C.I.C. + * Copyright 2026 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt index 6872786bdd2..fd228578c7f 100644 --- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt +++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/session/homeserver/DefaultGetHomeServerCapabilitiesTaskTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Matrix.org Foundation C.I.C. + * Copyright 2026 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From a631d85d9d2f7bdfe603b2f93b5bdd1810ec29b2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Jan 2026 09:46:05 +0100 Subject: [PATCH 13/27] Add missing Realm migration. Should have been added in #9102 --- .../database/RealmSessionStoreMigration.kt | 4 ++- .../database/migration/MigrateSessionTo057.kt | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt index cee831f37ac..ec946cb8800 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/RealmSessionStoreMigration.kt @@ -73,6 +73,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo053 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo054 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo055 import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo056 +import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo057 import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration import javax.inject.Inject @@ -81,7 +82,7 @@ internal class RealmSessionStoreMigration @Inject constructor( private val normalizer: Normalizer ) : MatrixRealmMigration( dbName = "Session", - schemaVersion = 56L, + schemaVersion = 57L, ) { /** * Forces all RealmSessionStoreMigration instances to be equal. @@ -147,5 +148,6 @@ internal class RealmSessionStoreMigration @Inject constructor( if (oldVersion < 54) MigrateSessionTo054(realm).perform() if (oldVersion < 55) MigrateSessionTo055(realm).perform() if (oldVersion < 56) MigrateSessionTo056(realm).perform() + if (oldVersion < 57) MigrateSessionTo057(realm).perform() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt new file mode 100644 index 00000000000..d3823718b2e --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.internal.database.migration + +import io.realm.DynamicRealm +import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEntityFields +import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities +import org.matrix.android.sdk.internal.util.database.RealmMigrator + +internal class MigrateSessionTo057(realm: DynamicRealm) : RealmMigrator(realm, 57) { + override fun doMigrate(realm: DynamicRealm) { + realm.schema.get("HomeServerCapabilitiesEntity") + ?.addField(HomeServerCapabilitiesEntityFields.EXTERNAL_ACCOUNT_MANAGEMENT_SUPPORTED_ACTIONS, String::class.java) + ?.forceRefreshOfHomeServerCapabilities() + } +} From e8bc6e96bb756fed636c94b82eb3fb900149cf8d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 16 Jan 2026 09:49:17 +0100 Subject: [PATCH 14/27] Fix data --- .../sdk/internal/database/migration/MigrateSessionTo057.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt index d3823718b2e..1739b2fe711 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo057.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 The Matrix.org Foundation C.I.C. + * Copyright (c) 2026 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 274d1fceed297f4eadf45bf8d46cbd20497ad99c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Jan 2026 13:44:24 +0100 Subject: [PATCH 15/27] Upgrade org.matrix.rustcomponents:crypto-android to 26.1.22 --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 8586e0077b0..e1a9828d76d 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -221,7 +221,7 @@ dependencies { implementation libs.google.phonenumber - implementation("org.matrix.rustcomponents:crypto-android:26.1.4") + implementation("org.matrix.rustcomponents:crypto-android:26.1.22") // api project(":library:rustCrypto") testImplementation libs.tests.junit From e618f2bb5f3c0f10d84902bba87c80e4a341ad29 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Jan 2026 14:28:29 +0100 Subject: [PATCH 16/27] Fix API break. --- .../org/matrix/android/sdk/internal/crypto/OlmMachine.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt index bbc4c3bb399..2b68e228b9c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OlmMachine.kt @@ -287,7 +287,14 @@ internal class OlmMachine @Inject constructor( val events = adapter.toJson(toDevice ?: ToDeviceSyncResponse()) // field pass in the list of unused fallback keys here - val receiveSyncChanges = inner.receiveSyncChanges(events, devices, counts, deviceUnusedFallbackKeyTypes, nextBatch ?: "") + val receiveSyncChanges = inner.receiveSyncChanges( + events = events, + deviceChanges = devices, + keyCounts = counts, + unusedFallbackKeys = deviceUnusedFallbackKeyTypes, + nextBatchToken = nextBatch ?: "", + decryptionSettings = DecryptionSettings(TrustRequirement.UNTRUSTED), + ) val outAdapter = moshi.adapter(Event::class.java) From 5f2df44c91e1e9f3bf2f30543bd0b34924b415d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Jan 2026 14:59:02 +0100 Subject: [PATCH 17/27] Upgrade Realm plugin to 10.19.0 This version supports 16k memory alignment. --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 70109c63c0f..058e718409c 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -17,7 +17,7 @@ buildscript { } } dependencies { - classpath "io.realm:realm-gradle-plugin:10.18.0" + classpath "io.realm:realm-gradle-plugin:10.19.0" } } From 306681f27311e5f5f65b82f1e4d4a0c68cf4ee68 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 22 Jan 2026 15:00:28 +0100 Subject: [PATCH 18/27] Changelog --- changelog.d/9111.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/9111.misc diff --git a/changelog.d/9111.misc b/changelog.d/9111.misc new file mode 100644 index 00000000000..c0efc587ef4 --- /dev/null +++ b/changelog.d/9111.misc @@ -0,0 +1 @@ +Update realm plugin to 10.19.0 From 6aeca83ac0322b09c6b6f0d100406f2bf779b2bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 23:12:26 +0000 Subject: [PATCH 19/27] Bump org.matrix.rustcomponents:crypto-android from 26.1.22 to 26.1.28 Bumps [org.matrix.rustcomponents:crypto-android](https://github.com/matrix-org/matrix-rust-components-kotlin) from 26.1.22 to 26.1.28. - [Release notes](https://github.com/matrix-org/matrix-rust-components-kotlin/releases) - [Commits](https://github.com/matrix-org/matrix-rust-components-kotlin/compare/sdk-v26.01.22...crypto-v26.1.28) --- updated-dependencies: - dependency-name: org.matrix.rustcomponents:crypto-android dependency-version: 26.1.28 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- matrix-sdk-android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 942aa6ecbba..f1e3f30e978 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -221,7 +221,7 @@ dependencies { implementation libs.google.phonenumber - implementation("org.matrix.rustcomponents:crypto-android:26.1.22") + implementation("org.matrix.rustcomponents:crypto-android:26.1.28") // api project(":library:rustCrypto") testImplementation libs.tests.junit From 5a925d98a20a1e343c1c5f1a4bfcf3dfbf59efc6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Feb 2026 15:22:08 +0100 Subject: [PATCH 20/27] Update Sentry dependency to version 8.31.0 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index d3e839a118d..316df1089e0 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -26,7 +26,7 @@ def glide = "4.16.0" def bigImageViewer = "1.8.1" def jjwt = "0.11.5" def vanniktechEmoji = "0.16.0" -def sentry = "6.18.1" +def sentry = "8.31.0" def fragment = "1.8.6" // Testing def mockk = "1.13.11" From 21c3f01baf9028e86038e55e325f04050f994d31 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Feb 2026 15:31:24 +0100 Subject: [PATCH 21/27] Fix compilation issue. --- .../metrics/sentry/SentrySyncDurationMetrics.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/analytics/metrics/sentry/SentrySyncDurationMetrics.kt b/vector/src/main/java/im/vector/app/features/analytics/metrics/sentry/SentrySyncDurationMetrics.kt index 877e4c3450f..65e5fe542c4 100644 --- a/vector/src/main/java/im/vector/app/features/analytics/metrics/sentry/SentrySyncDurationMetrics.kt +++ b/vector/src/main/java/im/vector/app/features/analytics/metrics/sentry/SentrySyncDurationMetrics.kt @@ -11,6 +11,7 @@ import io.sentry.ISpan import io.sentry.ITransaction import io.sentry.Sentry import io.sentry.SpanStatus +import io.sentry.TransactionOptions import org.matrix.android.sdk.api.metrics.SyncDurationMetricPlugin import java.util.EmptyStackException import java.util.Stack @@ -58,7 +59,13 @@ class SentrySyncDurationMetrics @Inject constructor() : SyncDurationMetricPlugin override fun startTransaction() { if (Sentry.isEnabled()) { - transaction = Sentry.startTransaction("sync_response_handler", "task", true) + transaction = Sentry.startTransaction( + "sync_response_handler", + "task", + TransactionOptions().apply { + isBindToScope = true + }, + ) logTransaction("Sentry transaction started") } } From 2b07e16254f12b5c20536d50e6d3515049a4a194 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Feb 2026 17:13:25 +0100 Subject: [PATCH 22/27] Update Maplibre dependency to version 11.6.1 https://github.com/maplibre/maplibre-native/blob/main/platform/android/CHANGELOG.md#1161 --- dependencies.gradle | 4 +-- .../java/im/vector/app/VectorApplication.kt | 4 +-- .../location/LocationSharingFragment.kt | 2 +- .../app/features/location/MapBoxMapExt.kt | 18 ++++++------ .../app/features/location/MapTilerMapView.kt | 24 ++++++++-------- .../domain/usecase/CompareLocationsUseCase.kt | 2 +- .../live/map/LiveLocationMapViewFragment.kt | 28 +++++++++---------- .../preview/LocationPreviewFragment.kt | 2 +- 8 files changed, 42 insertions(+), 42 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index d3e839a118d..d3ab7bfd210 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -132,8 +132,8 @@ ext.libs = [ 'mavericksTesting' : "com.airbnb.android:mavericks-testing:$mavericks" ], maplibre : [ - 'androidSdk' : "org.maplibre.gl:android-sdk:10.0.2", - 'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:1.0.0" + 'androidSdk' : "org.maplibre.gl:android-sdk:11.6.1", + 'pluginAnnotation' : "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" ], mockk : [ 'mockk' : "io.mockk:mockk:$mockk", diff --git a/vector-app/src/main/java/im/vector/app/VectorApplication.kt b/vector-app/src/main/java/im/vector/app/VectorApplication.kt index 84b87b14040..f051feffeef 100644 --- a/vector-app/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector-app/src/main/java/im/vector/app/VectorApplication.kt @@ -33,7 +33,6 @@ import com.airbnb.mvrx.Mavericks import com.facebook.stetho.Stetho import com.gabrielittner.threetenbp.LazyThreeTen import com.github.rubensousa.gravitysnaphelper.GravitySnapHelper -import com.mapbox.mapboxsdk.Mapbox import com.vanniktech.emoji.EmojiManager import com.vanniktech.emoji.google.GoogleEmojiProvider import dagger.hilt.android.HiltAndroidApp @@ -62,6 +61,7 @@ import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.version.VersionProvider import im.vector.application.R import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler +import org.maplibre.android.MapLibre import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.auth.AuthenticationService import timber.log.Timber @@ -223,7 +223,7 @@ class VectorApplication : EmojiManager.install(GoogleEmojiProvider()) // Initialize Mapbox before inflating mapViews - Mapbox.getInstance(this) + MapLibre.getInstance(this) initMemoryLeakAnalysis() } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index d5b0850ce8a..2995a37ec2d 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -21,7 +21,7 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.mapbox.mapboxsdk.maps.MapView +import org.maplibre.android.maps.MapView import dagger.hilt.android.AndroidEntryPoint import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseFragment diff --git a/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt b/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt index c187757dc70..be88d5809b5 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapBoxMapExt.kt @@ -7,14 +7,14 @@ package im.vector.app.features.location -import com.mapbox.mapboxsdk.camera.CameraPosition -import com.mapbox.mapboxsdk.camera.CameraUpdateFactory -import com.mapbox.mapboxsdk.constants.MapboxConstants -import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.geometry.LatLngBounds -import com.mapbox.mapboxsdk.maps.MapboxMap +import org.maplibre.android.camera.CameraPosition +import org.maplibre.android.camera.CameraUpdateFactory +import org.maplibre.android.constants.MapLibreConstants +import org.maplibre.android.geometry.LatLng +import org.maplibre.android.geometry.LatLngBounds +import org.maplibre.android.maps.MapLibreMap -fun MapboxMap?.zoomToLocation(locationData: LocationData, preserveCurrentZoomLevel: Boolean = false) { +fun MapLibreMap?.zoomToLocation(locationData: LocationData, preserveCurrentZoomLevel: Boolean = false) { val zoomLevel = if (preserveCurrentZoomLevel && this?.cameraPosition != null) { cameraPosition.zoom } else { @@ -28,11 +28,11 @@ fun MapboxMap?.zoomToLocation(locationData: LocationData, preserveCurrentZoomLev this?.easeCamera(cameraUpdate) } -fun MapboxMap?.zoomToBounds(latLngBounds: LatLngBounds) { +fun MapLibreMap?.zoomToBounds(latLngBounds: LatLngBounds) { this?.getCameraForLatLngBounds(latLngBounds)?.let { camPosition -> // unZoom a little to avoid having pins exactly at the edges of the map cameraPosition = CameraPosition.Builder(camPosition) - .zoom((camPosition.zoom - 1).coerceAtLeast(MapboxConstants.MINIMUM_ZOOM.toDouble())) + .zoom((camPosition.zoom - 1).coerceAtLeast(MapLibreConstants.MINIMUM_ZOOM.toDouble())) .build() } } diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt index 15af86a4da7..7e8d0f1867c 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -19,13 +19,13 @@ import androidx.core.graphics.drawable.toBitmap import androidx.core.view.marginBottom import androidx.core.view.marginTop import androidx.core.view.updateLayoutParams -import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.maps.MapView -import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.maps.Style -import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager -import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions -import com.mapbox.mapboxsdk.style.layers.Property +import org.maplibre.android.geometry.LatLng +import org.maplibre.android.maps.MapView +import org.maplibre.android.maps.MapLibreMap +import org.maplibre.android.maps.Style +import org.maplibre.android.plugins.annotation.SymbolManager +import org.maplibre.android.plugins.annotation.SymbolOptions +import org.maplibre.android.style.layers.Property import im.vector.app.R import im.vector.app.core.utils.DimensionConverter import im.vector.lib.strings.CommonStrings @@ -42,7 +42,7 @@ class MapTilerMapView @JvmOverloads constructor( private var pendingState: MapState? = null data class MapRefs( - val map: MapboxMap, + val map: MapLibreMap, val symbolManager: SymbolManager, val style: Style ) @@ -94,7 +94,7 @@ class MapTilerMapView @JvmOverloads constructor( } } - private fun initMapStyle(map: MapboxMap, url: String) { + private fun initMapStyle(map: MapLibreMap, url: String) { map.setStyle(url) { style -> val symbolManager = SymbolManager(this, map, style) symbolManager.iconAllowOverlap = true @@ -108,7 +108,7 @@ class MapTilerMapView @JvmOverloads constructor( } } - private fun initLocateButton(map: MapboxMap) { + private fun initLocateButton(map: MapLibreMap) { if (showLocationButton) { addView(locateButton) adjustCompassButton(map) @@ -132,7 +132,7 @@ class MapTilerMapView @JvmOverloads constructor( } } - private fun adjustCompassButton(map: MapboxMap) { + private fun adjustCompassButton(map: MapLibreMap) { locateButton.post { val marginTop = locateButton.height + locateButton.marginTop + locateButton.marginBottom val marginRight = context.resources.getDimensionPixelOffset(im.vector.lib.ui.styles.R.dimen.location_sharing_compass_button_margin_horizontal) @@ -140,7 +140,7 @@ class MapTilerMapView @JvmOverloads constructor( } } - private fun listenCameraMove(map: MapboxMap, locationTargetChangeListener: LocationTargetChangeListener?) { + private fun listenCameraMove(map: MapLibreMap, locationTargetChangeListener: LocationTargetChangeListener?) { map.addOnCameraMoveListener { notifyLocationOfMapCenter(locationTargetChangeListener) } diff --git a/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt b/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt index 9c17ea8be30..1ac5bd4754f 100644 --- a/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt @@ -7,7 +7,7 @@ package im.vector.app.features.location.domain.usecase -import com.mapbox.mapboxsdk.geometry.LatLng +import org.maplibre.android.geometry.LatLng import im.vector.app.features.location.LocationData import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.session.Session diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt index dae3fe5acbc..b121c894801 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt @@ -21,18 +21,18 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.mapbox.mapboxsdk.geometry.LatLng -import com.mapbox.mapboxsdk.geometry.LatLngBounds -import com.mapbox.mapboxsdk.maps.MapView -import com.mapbox.mapboxsdk.maps.MapboxMap -import com.mapbox.mapboxsdk.maps.MapboxMapOptions -import com.mapbox.mapboxsdk.maps.Style -import com.mapbox.mapboxsdk.maps.SupportMapFragment -import com.mapbox.mapboxsdk.plugins.annotation.OnSymbolClickListener -import com.mapbox.mapboxsdk.plugins.annotation.Symbol -import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager -import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions -import com.mapbox.mapboxsdk.style.layers.Property +import org.maplibre.android.geometry.LatLng +import org.maplibre.android.geometry.LatLngBounds +import org.maplibre.android.maps.MapView +import org.maplibre.android.maps.MapLibreMap +import org.maplibre.android.maps.MapLibreMapOptions +import org.maplibre.android.maps.Style +import org.maplibre.android.maps.SupportMapFragment +import org.maplibre.android.plugins.annotation.OnSymbolClickListener +import org.maplibre.android.plugins.annotation.Symbol +import org.maplibre.android.plugins.annotation.SymbolManager +import org.maplibre.android.plugins.annotation.SymbolOptions +import org.maplibre.android.style.layers.Property import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.addChildFragment @@ -74,7 +74,7 @@ class LiveLocationMapViewFragment : private val viewModel: LiveLocationMapViewModel by fragmentViewModel() - private var mapboxMap: WeakReference? = null + private var mapboxMap: WeakReference? = null private var mapView: MapView? = null private var symbolManager: SymbolManager? = null private var mapStyle: Style? = null @@ -214,7 +214,7 @@ class LiveLocationMapViewFragment : private fun getOrCreateSupportMapFragment() = childFragmentManager.findFragmentByTag(MAP_FRAGMENT_TAG) as? SupportMapFragment ?: run { - val options = MapboxMapOptions.createFromAttributes(requireContext(), null) + val options = MapLibreMapOptions.createFromAttributes(requireContext(), null) SupportMapFragment.newInstance(options) .also { addChildFragment(R.id.liveLocationMapFragmentContainer, it, tag = MAP_FRAGMENT_TAG) } } diff --git a/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt index 62ea85ee9fe..1e451fe8622 100644 --- a/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt @@ -17,7 +17,7 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import com.mapbox.mapboxsdk.maps.MapView +import org.maplibre.android.maps.MapView import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment From 82e835ea91a4b0934c868070fb41cc9a76d48765 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Feb 2026 18:02:50 +0100 Subject: [PATCH 23/27] Remove flipper from the codebase. The library is not maintained anymore. Part of #9086 --- dependencies.gradle | 5 -- dependencies_groups.gradle | 2 - docs/flipper.md | 58 -------------- vector-app/build.gradle | 10 --- vector-app/src/debug/AndroidManifest.xml | 5 -- .../app/features/debug/di/DebugModule.kt | 5 -- .../vector/app/flipper/VectorFlipperProxy.kt | 76 ------------------- .../java/im/vector/app/VectorApplication.kt | 3 - .../im/vector/app/core/di/SingletonModule.kt | 6 +- .../java/im/vector/app/core/di/DebugModule.kt | 10 --- .../im/vector/app/core/debug/FlipperProxy.kt | 16 ---- 11 files changed, 1 insertion(+), 195 deletions(-) delete mode 100644 docs/flipper.md delete mode 100644 vector-app/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt delete mode 100644 vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt diff --git a/dependencies.gradle b/dependencies.gradle index d3e839a118d..8ab397e95b5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -19,7 +19,6 @@ def markwon = "4.6.2" def moshi = "1.15.1" def lifecycle = "2.8.3" def flowBinding = "1.2.0" -def flipper = "0.259.0" def epoxy = "5.0.0" def mavericks = "3.0.9" def glide = "4.16.0" @@ -95,10 +94,6 @@ ext.libs = [ 'hiltAndroidTesting' : "com.google.dagger:hilt-android-testing:$dagger", 'hiltCompiler' : "com.google.dagger:hilt-compiler:$dagger" ], - flipper : [ - 'flipper' : "com.facebook.flipper:flipper:$flipper", - 'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper", - ], element : [ 'opusencoder' : "io.element.android:opusencoder:1.1.0", 'wysiwyg' : "io.element.android:wysiwyg:2.38.2" diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 282fa353e4f..59cc63896f6 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -69,7 +69,6 @@ ext.groups = [ 'com.dropbox.core', 'com.soywiz.korlibs.korte', 'com.facebook.fbjni', - 'com.facebook.flipper', 'com.facebook.fresco', 'com.facebook.infer.annotation', 'com.facebook.react', @@ -114,7 +113,6 @@ ext.groups = [ 'com.intellij', 'com.jakewharton.android.repackaged', 'com.jakewharton.timber', - 'com.kgurgul.flipper', 'com.linkedin.dexmaker', 'com.mapbox.mapboxsdk', 'com.nulab-inc', diff --git a/docs/flipper.md b/docs/flipper.md deleted file mode 100644 index 495425ce5f4..00000000000 --- a/docs/flipper.md +++ /dev/null @@ -1,58 +0,0 @@ -# Flipper - - - -* [Introduction](#introduction) -* [Setup](#setup) - * [Troubleshoot](#troubleshoot) - * [No device found issue](#no-device-found-issue) - * [Diagnostic Activity](#diagnostic-activity) - * [Other](#other) -* [Links](#links) - - - -## Introduction - -[Flipper](https://fbflipper.com) is a powerful tool from Meta, which allow to inspect the running application details and states from your computer. - -Flipper is configured in the Element Android project to let the developers be able to: -- inspect all the Realm databases content; -- do layout inspection; -- see the crash logs; -- see the logcat; -- see all the network requests; -- see all the SharedPreferences; -- take screenshots and record videos of the device; -- and more! - -## Setup - -- Install Flipper on your computer. Follow instructions here: https://fbflipper.com/docs/getting-started/index/ -- Run the debug version of Element on an emulator or on a real device. - -### Troubleshoot - -#### No device found issue - -The configuration of the Flipper application has to be updated. The issue has been asked and answered here: https://stackoverflow.com/questions/71744103/android-emulator-unable-to-connect-to-flipper/72608113#72608113 - -#### Diagnostic Activity - -Flipper comes with a Diagnostic Activity that you can start from command line using: - -```shell -adb shell am start -n im.vector.app.debug/com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity -``` - -It provides some log which can help to figure out what's going on client side. - -#### Other - -https://fbflipper.com/docs/getting-started/troubleshooting/android/ may help. - -## Links - -- Official Flipper website: https://fbflipper.com -- Realm Plugin for Flipper: https://github.com/kamgurgul/Flipper-Realm -- Dedicated Matrix room: https://matrix.to/#/#unifiedpush:matrix.org diff --git a/vector-app/build.gradle b/vector-app/build.gradle index 1905e397f5f..bdc705bd76c 100644 --- a/vector-app/build.gradle +++ b/vector-app/build.gradle @@ -391,16 +391,6 @@ dependencies { implementation 'androidx.multidex:multidex:2.0.1' implementation "androidx.sharetarget:sharetarget:1.2.0" - // Flipper, debug builds only - debugImplementation(libs.flipper.flipper) { - exclude group: 'com.facebook.fbjni', module: 'fbjni' - } - debugImplementation(libs.flipper.flipperNetworkPlugin) { - exclude group: 'com.facebook.fbjni', module: 'fbjni' - } - debugImplementation 'com.facebook.soloader:soloader:0.10.5' - debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.3.0" - gplayImplementation "com.google.android.gms:play-services-location:21.3.0" // UnifiedPush gplay flavor only gplayImplementation platform(libs.google.firebaseBom) diff --git a/vector-app/src/debug/AndroidManifest.xml b/vector-app/src/debug/AndroidManifest.xml index be2aadbeaf8..4f1d6817531 100644 --- a/vector-app/src/debug/AndroidManifest.xml +++ b/vector-app/src/debug/AndroidManifest.xml @@ -11,11 +11,6 @@ - - - diff --git a/vector-app/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt b/vector-app/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt index 6604545ca4c..b5af29f7e08 100644 --- a/vector-app/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt +++ b/vector-app/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt @@ -16,10 +16,8 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import im.vector.app.core.debug.DebugNavigator import im.vector.app.core.debug.DebugReceiver -import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.debug.LeakDetector import im.vector.app.features.debug.DebugMenuActivity -import im.vector.app.flipper.VectorFlipperProxy import im.vector.app.leakcanary.LeakCanaryLeakDetector import im.vector.app.receivers.VectorDebugReceiver @@ -40,9 +38,6 @@ abstract class DebugModule { @Binds abstract fun bindsDebugReceiver(receiver: VectorDebugReceiver): DebugReceiver - @Binds - abstract fun bindsFlipperProxy(flipperProxy: VectorFlipperProxy): FlipperProxy - @Binds abstract fun bindsLeakDetector(leakDetector: LeakCanaryLeakDetector): LeakDetector } diff --git a/vector-app/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt b/vector-app/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt deleted file mode 100644 index fca6278d7d3..00000000000 --- a/vector-app/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2022-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 im.vector.app.flipper - -import android.content.Context -import android.os.Build -import com.facebook.flipper.android.AndroidFlipperClient -import com.facebook.flipper.android.utils.FlipperUtils -import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin -import com.facebook.flipper.plugins.inspector.DescriptorMapping -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin -import com.facebook.soloader.SoLoader -import com.kgurgul.flipper.RealmDatabaseDriver -import com.kgurgul.flipper.RealmDatabaseProvider -import im.vector.app.core.debug.FlipperProxy -import io.realm.RealmConfiguration -import okhttp3.Interceptor -import org.matrix.android.sdk.api.Matrix -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class VectorFlipperProxy @Inject constructor( - private val context: Context, -) : FlipperProxy { - private val networkFlipperPlugin = NetworkFlipperPlugin() - - private val isEnabled: Boolean - get() { - // https://github.com/facebook/flipper/issues/3572 - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) { - return false - } - - return FlipperUtils.shouldEnableFlipper(context) - } - - override fun init(matrix: Matrix) { - if (!isEnabled) return - - SoLoader.init(context, false) - - val client = AndroidFlipperClient.getInstance(context) - client.addPlugin(CrashReporterPlugin.getInstance()) - client.addPlugin(SharedPreferencesFlipperPlugin(context)) - client.addPlugin(InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())) - client.addPlugin(networkFlipperPlugin) - client.addPlugin( - DatabasesFlipperPlugin( - RealmDatabaseDriver( - context = context, - realmDatabaseProvider = object : RealmDatabaseProvider { - override fun getRealmConfigurations(): List { - return matrix.debugService().getAllRealmConfigurations() - } - }) - ) - ) - client.start() - } - - override fun networkInterceptor(): Interceptor? { - if (!isEnabled) return null - - return FlipperOkhttpInterceptor(networkFlipperPlugin) - } -} diff --git a/vector-app/src/main/java/im/vector/app/VectorApplication.kt b/vector-app/src/main/java/im/vector/app/VectorApplication.kt index 84b87b14040..f984729c57a 100644 --- a/vector-app/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector-app/src/main/java/im/vector/app/VectorApplication.kt @@ -38,7 +38,6 @@ import com.vanniktech.emoji.EmojiManager import com.vanniktech.emoji.google.GoogleEmojiProvider import dagger.hilt.android.HiltAndroidApp import im.vector.app.config.Config -import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.debug.LeakDetector import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.pushers.FcmHelper @@ -97,7 +96,6 @@ class VectorApplication : @Inject lateinit var decryptionFailureTracker: DecryptionFailureTracker @Inject lateinit var vectorFileLogger: VectorFileLogger @Inject lateinit var vectorAnalytics: VectorAnalytics - @Inject lateinit var flipperProxy: FlipperProxy @Inject lateinit var matrix: Matrix @Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var buildMeta: BuildMeta @@ -121,7 +119,6 @@ class VectorApplication : enableStrictModeIfNeeded() super.onCreate() appContext = this - flipperProxy.init(matrix) vectorAnalytics.init() vectorAnalytics.updateSuperProperties( SuperProperties( diff --git a/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt index 4f1180303a3..49f0fd7aae3 100644 --- a/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector-app/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -24,7 +24,6 @@ import im.vector.app.EmojiSpanify import im.vector.app.SpaceStateHandler import im.vector.app.SpaceStateHandlerImpl import im.vector.app.config.Config -import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.device.DefaultGetDeviceInfoUseCase import im.vector.app.core.device.GetDeviceInfoUseCase import im.vector.app.core.dispatchers.CoroutineDispatchers @@ -140,7 +139,6 @@ import javax.inject.Singleton fun providesMatrixConfiguration( vectorPreferences: VectorPreferences, vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider, - flipperProxy: FlipperProxy, vectorPlugins: VectorPlugins, vectorCustomEventTypesProvider: VectorCustomEventTypesProvider, mdmService: MdmService, @@ -149,9 +147,7 @@ import javax.inject.Singleton applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION, roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider, threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(), - networkInterceptors = listOfNotNull( - flipperProxy.networkInterceptor(), - ), + networkInterceptors = emptyList(), metricPlugins = vectorPlugins.plugins(), cryptoAnalyticsPlugin = vectorPlugins.cryptoMetricPlugin, customEventTypesProvider = vectorCustomEventTypesProvider, diff --git a/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt b/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt index 89a2d184842..25085ccb2ba 100644 --- a/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt +++ b/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt @@ -14,7 +14,6 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import im.vector.app.core.debug.DebugNavigator import im.vector.app.core.debug.DebugReceiver -import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.debug.LeakDetector import okhttp3.Interceptor import org.matrix.android.sdk.api.Matrix @@ -41,15 +40,6 @@ object DebugModule { } } - @Provides - fun providesFlipperProxy() = object : FlipperProxy { - override fun init(matrix: Matrix) { - // no op - } - - override fun networkInterceptor(): Interceptor? = null - } - @Provides fun providesLeakDetector() = object : LeakDetector { override fun enable(enable: Boolean) { diff --git a/vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt b/vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt deleted file mode 100644 index d3dc4b346ee..00000000000 --- a/vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022-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 im.vector.app.core.debug - -import okhttp3.Interceptor -import org.matrix.android.sdk.api.Matrix - -interface FlipperProxy { - fun init(matrix: Matrix) - fun networkInterceptor(): Interceptor? -} From 1cda5eb8f853e75f2118ba4ce939f7e69ab34317 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 2 Feb 2026 18:20:11 +0100 Subject: [PATCH 24/27] Reorder import statements --- .../location/LocationSharingFragment.kt | 2 +- .../app/features/location/MapTilerMapView.kt | 8 +++---- .../domain/usecase/CompareLocationsUseCase.kt | 2 +- .../live/map/LiveLocationMapViewFragment.kt | 24 +++++++++---------- .../preview/LocationPreviewFragment.kt | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index 2995a37ec2d..069c6686c81 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -21,7 +21,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder -import org.maplibre.android.maps.MapView import dagger.hilt.android.AndroidEntryPoint import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.app.core.platform.VectorBaseFragment @@ -39,6 +38,7 @@ import im.vector.app.features.location.option.LocationSharingOption import im.vector.app.features.settings.VectorPreferences import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch +import org.maplibre.android.maps.MapView import org.matrix.android.sdk.api.util.MatrixItem import java.lang.ref.WeakReference import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt index 7e8d0f1867c..cfce7dffec3 100644 --- a/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt +++ b/vector/src/main/java/im/vector/app/features/location/MapTilerMapView.kt @@ -19,16 +19,16 @@ import androidx.core.graphics.drawable.toBitmap import androidx.core.view.marginBottom import androidx.core.view.marginTop import androidx.core.view.updateLayoutParams +import im.vector.app.R +import im.vector.app.core.utils.DimensionConverter +import im.vector.lib.strings.CommonStrings import org.maplibre.android.geometry.LatLng -import org.maplibre.android.maps.MapView import org.maplibre.android.maps.MapLibreMap +import org.maplibre.android.maps.MapView import org.maplibre.android.maps.Style import org.maplibre.android.plugins.annotation.SymbolManager import org.maplibre.android.plugins.annotation.SymbolOptions import org.maplibre.android.style.layers.Property -import im.vector.app.R -import im.vector.app.core.utils.DimensionConverter -import im.vector.lib.strings.CommonStrings import timber.log.Timber private const val USER_PIN_ID = "user-pin-id" diff --git a/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt b/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt index 1ac5bd4754f..00c05ca4acf 100644 --- a/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/location/domain/usecase/CompareLocationsUseCase.kt @@ -7,9 +7,9 @@ package im.vector.app.features.location.domain.usecase -import org.maplibre.android.geometry.LatLng import im.vector.app.features.location.LocationData import kotlinx.coroutines.withContext +import org.maplibre.android.geometry.LatLng import org.matrix.android.sdk.api.session.Session import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt index b121c894801..7f5ce8c5480 100644 --- a/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/live/map/LiveLocationMapViewFragment.kt @@ -21,18 +21,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.bottomsheet.BottomSheetBehavior -import org.maplibre.android.geometry.LatLng -import org.maplibre.android.geometry.LatLngBounds -import org.maplibre.android.maps.MapView -import org.maplibre.android.maps.MapLibreMap -import org.maplibre.android.maps.MapLibreMapOptions -import org.maplibre.android.maps.Style -import org.maplibre.android.maps.SupportMapFragment -import org.maplibre.android.plugins.annotation.OnSymbolClickListener -import org.maplibre.android.plugins.annotation.Symbol -import org.maplibre.android.plugins.annotation.SymbolManager -import org.maplibre.android.plugins.annotation.SymbolOptions -import org.maplibre.android.style.layers.Property import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.addChildFragment @@ -54,6 +42,18 @@ import im.vector.app.features.location.zoomToBounds import im.vector.app.features.location.zoomToLocation import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch +import org.maplibre.android.geometry.LatLng +import org.maplibre.android.geometry.LatLngBounds +import org.maplibre.android.maps.MapLibreMap +import org.maplibre.android.maps.MapLibreMapOptions +import org.maplibre.android.maps.MapView +import org.maplibre.android.maps.Style +import org.maplibre.android.maps.SupportMapFragment +import org.maplibre.android.plugins.annotation.OnSymbolClickListener +import org.maplibre.android.plugins.annotation.Symbol +import org.maplibre.android.plugins.annotation.SymbolManager +import org.maplibre.android.plugins.annotation.SymbolOptions +import org.maplibre.android.style.layers.Property import timber.log.Timber import java.lang.ref.WeakReference import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt index 1e451fe8622..84ac2a34cd6 100644 --- a/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/preview/LocationPreviewFragment.kt @@ -17,7 +17,6 @@ import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import org.maplibre.android.maps.MapView import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment @@ -35,6 +34,7 @@ import im.vector.app.features.location.UrlMapProvider import im.vector.app.features.location.showUserLocationNotAvailableErrorDialog import im.vector.lib.strings.CommonStrings import kotlinx.coroutines.launch +import org.maplibre.android.maps.MapView import java.lang.ref.WeakReference import javax.inject.Inject From 5f370f805c1255812f819809f13a96be86206012 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 3 Feb 2026 09:03:53 +0100 Subject: [PATCH 25/27] Remove unused import statements. --- .../src/release/java/im/vector/app/core/di/DebugModule.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt b/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt index 25085ccb2ba..2819bc9c821 100644 --- a/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt +++ b/vector-app/src/release/java/im/vector/app/core/di/DebugModule.kt @@ -15,8 +15,6 @@ import dagger.hilt.components.SingletonComponent import im.vector.app.core.debug.DebugNavigator import im.vector.app.core.debug.DebugReceiver import im.vector.app.core.debug.LeakDetector -import okhttp3.Interceptor -import org.matrix.android.sdk.api.Matrix @InstallIn(SingletonComponent::class) @Module From c97572756ae1fd477564e141aebce960b88cff17 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Feb 2026 09:50:32 +0100 Subject: [PATCH 26/27] Changelog for version 1.6.50 --- CHANGES.md | 13 +++++++++++++ changelog.d/9097.misc | 1 - changelog.d/9102.misc | 1 - changelog.d/9111.misc | 1 - 4 files changed, 13 insertions(+), 3 deletions(-) delete mode 100644 changelog.d/9097.misc delete mode 100644 changelog.d/9102.misc delete mode 100644 changelog.d/9111.misc diff --git a/CHANGES.md b/CHANGES.md index 1038417058e..595baee9e11 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,16 @@ +Changes in Element v1.6.50 (2026-02-04) +======================================= + +Other changes +------------- + - Update the default bug reporting URL. ([#9097](https://github.com/element-hq/element-android/issues/9097)) + - Update OAuth-awareness to support the stable version of MSC3824. ([#9102](https://github.com/element-hq/element-android/issues/9102)) + - Update realm plugin to 10.19.0 ([#9111](https://github.com/element-hq/element-android/issues/9116)) + - Bump org.matrix.rustcomponents:crypto-android from 26.1.22 to 26.1.28 ([#9114](https://github.com/element-hq/element-android/issues/9114)) + - Update sentry to version 8.31.0 ([#9115](https://github.com/element-hq/element-android/issues/9115)) + - Update Maplibre dependency to version 11.6.1 ([#9116](https://github.com/element-hq/element-android/issues/9116)) + - Remove flipper from the codebase. ([#9117](https://github.com/element-hq/element-android/issues/9117)) + Changes in Element v1.6.48 (2025-10-15) ======================================= diff --git a/changelog.d/9097.misc b/changelog.d/9097.misc deleted file mode 100644 index 7a20e030876..00000000000 --- a/changelog.d/9097.misc +++ /dev/null @@ -1 +0,0 @@ -Update the default bug reporting URL. diff --git a/changelog.d/9102.misc b/changelog.d/9102.misc deleted file mode 100644 index 705a7a57fbd..00000000000 --- a/changelog.d/9102.misc +++ /dev/null @@ -1 +0,0 @@ -Update OAuth-awareness to support the stable version of MSC3824. diff --git a/changelog.d/9111.misc b/changelog.d/9111.misc deleted file mode 100644 index c0efc587ef4..00000000000 --- a/changelog.d/9111.misc +++ /dev/null @@ -1 +0,0 @@ -Update realm plugin to 10.19.0 From 7bf5c55a8aa4ab19a8577bfa2206b17c78ed95f5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 4 Feb 2026 09:51:05 +0100 Subject: [PATCH 27/27] Adding fastlane file for version 1.6.50 --- fastlane/metadata/android/en-US/changelogs/40106500.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40106500.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40106500.txt b/fastlane/metadata/android/en-US/changelogs/40106500.txt new file mode 100644 index 00000000000..73cd3e2bd9c --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40106500.txt @@ -0,0 +1,2 @@ +Main changes in this version: bug fixes and improvements. +Full changelog: https://github.com/element-hq/element-android/releases