Skip to content

Commit 4dbfa90

Browse files
committed
Merge branch 'release/25.06.0' into main
2 parents 0fab33a + 4e84e7d commit 4dbfa90

File tree

820 files changed

+10317
-4982
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

820 files changed

+10317
-4982
lines changed

.github/workflows/maestro-local.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ env:
1111
CI_GRADLE_ARG_PROPERTIES: --stacktrace --no-daemon -Dsonar.gradle.skipCompile=true --no-configuration-cache
1212
ARCH: x86_64
1313
DEVICE: pixel_7_pro
14-
API_LEVEL: 35
14+
API_LEVEL: 33
1515
TARGET: google_apis
1616

1717
jobs:

.maestro/allTests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
appId: ${MAESTRO_APP_ID}
2+
androidWebViewHierarchy: devtools
23
---
34
## Check that all env variables required in the whole test suite are declared (to fail faster)
45
- runScript: ./scripts/checkEnv.js

.maestro/tests/account/login.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,22 @@ appId: ${MAESTRO_APP_ID}
1414
visible: 'Use without an account'
1515
commands:
1616
- tapOn: "Use without an account"
17+
## For older chrome versions
18+
- runFlow:
19+
when:
20+
visible: 'Accept & continue'
21+
commands:
22+
- tapOn: "Accept & continue"
23+
- runFlow:
24+
when:
25+
visible: 'No thanks'
26+
commands:
27+
- tapOn: "No thanks"
1728
## Working when running Maestro locally, but not on the CI yet.
29+
- extendedWaitUntil:
30+
visible:
31+
id: "form-1"
32+
timeout: 10000
1833
- tapOn:
1934
id: "form-1"
2035
- inputText: ${MAESTRO_USERNAME}

CHANGES.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,50 @@
1+
<!-- Release notes generated using configuration in .github/release.yml at v25.05.4 -->
2+
3+
Changes in Element X v25.05.4
4+
=============================
5+
6+
Rust SDK: https://github.com/matrix-org/matrix-rust-sdk/releases/tag/matrix-sdk-ffi%2F20250521
7+
8+
## What's Changed
9+
### 🙌 Improvements
10+
* Change (report room) : check if server supports the report room api by @ganfra in https://github.com/element-hq/element-x-android/pull/4718
11+
### 🐛 Bugfixes
12+
* Improve audio focus management by @bmarty in https://github.com/element-hq/element-x-android/pull/4707
13+
* When transcoding a video fails, send it as a file by @jmartinesp in https://github.com/element-hq/element-x-android/pull/4257
14+
* Disable mutliple click (parallel or serial) on a room by @bmarty in https://github.com/element-hq/element-x-android/pull/4683
15+
* Fix generic mime type used when externally sharing several files by @jmartinesp in https://github.com/element-hq/element-x-android/pull/4715
16+
* Fix issues on JoinedRoom / BaseRoom by @bmarty in https://github.com/element-hq/element-x-android/pull/4724
17+
* Use the right live timeline instance in `RustRoomFactory` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/4745
18+
### 🗣 Translations
19+
* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/4739
20+
### 🧱 Build
21+
* Ensure the CI is marked as failed when Maestro test is failing by @bmarty in https://github.com/element-hq/element-x-android/pull/4700
22+
* Trigger pipeline build when a release tag is pushed by @bmarty in https://github.com/element-hq/element-x-android/pull/4741
23+
* Fix compilation issues. by @bmarty in https://github.com/element-hq/element-x-android/pull/4750
24+
### 📄 Documentation
25+
* README.md: fix broken link by @richvdh in https://github.com/element-hq/element-x-android/pull/4728
26+
### Dependency upgrades
27+
* chore(config): migrate renovate config by @renovate in https://github.com/element-hq/element-x-android/pull/4688
28+
* fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v25.5.13 by @renovate in https://github.com/element-hq/element-x-android/pull/4716
29+
* fix(deps): update dependency io.sentry:sentry-android to v8.12.0 by @renovate in https://github.com/element-hq/element-x-android/pull/4717
30+
* chore(deps): update plugin sonarqube to v6.2.0.5505 by @renovate in https://github.com/element-hq/element-x-android/pull/4725
31+
* fix(deps): update dependency com.posthog:posthog-android to v3.15.0 by @renovate in https://github.com/element-hq/element-x-android/pull/4723
32+
* fix(deps): update dependency com.squareup.retrofit2:retrofit-bom to v2.12.0 by @renovate in https://github.com/element-hq/element-x-android/pull/4727
33+
* chore(deps): update codecov/codecov-action action to v5.4.3 by @renovate in https://github.com/element-hq/element-x-android/pull/4730
34+
* fix(deps): update kotlin by @renovate in https://github.com/element-hq/element-x-android/pull/4713
35+
* fix(deps): update dependency com.squareup.retrofit2:retrofit-bom to v3 by @renovate in https://github.com/element-hq/element-x-android/pull/4729
36+
* fix(deps): update kotlinpoet to v2.2.0 by @renovate in https://github.com/element-hq/element-x-android/pull/4732
37+
* fix(deps): update dependency org.matrix.rustcomponents:sdk-android to v25.5.21 by @renovate in https://github.com/element-hq/element-x-android/pull/4759
38+
### Others
39+
* Remove event cache feature flag by @jmartinesp in https://github.com/element-hq/element-x-android/pull/4719
40+
* Check homeserver when login using qr code by @bmarty in https://github.com/element-hq/element-x-android/pull/4708
41+
* Merge on boarding module to login module by @bmarty in https://github.com/element-hq/element-x-android/pull/4746
42+
* Allow configuration to provide multiple account providers. by @bmarty in https://github.com/element-hq/element-x-android/pull/4742
43+
* Reduce API of JoinedRoom, caller must use the Timeline API from liveTimeline instead by @bmarty in https://github.com/element-hq/element-x-android/pull/4731
44+
45+
46+
**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v25.05.3...v25.05.4
47+
148
Changes in Element X v25.05.3
249
=============================
350

app/build.gradle.kts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,3 +354,12 @@ fun Project.configureLicensesTasks(reportingExtension: ReportingExtension) {
354354
}
355355
}
356356
}
357+
358+
configurations.all {
359+
resolutionStrategy {
360+
dependencySubstitution {
361+
val tink = libs.google.tink.get()
362+
substitute(module("com.google.crypto.tink:tink")).using(module("${tink.group}:${tink.name}:${tink.version}"))
363+
}
364+
}
365+
}

app/src/main/AndroidManifest.xml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,17 @@
3434
android:value='androidx.startup' />
3535
</provider>
3636

37+
<!--
38+
Using launchMode singleTask to avoid multiple instances of the Activity
39+
when the app is already open. This is important for incoming share (see
40+
https://github.com/element-hq/element-x-android/issues/4074) and for opening
41+
the application from a mobile.element.io link.
42+
-->
3743
<activity
3844
android:name=".MainActivity"
3945
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|uiMode"
4046
android:exported="true"
41-
android:launchMode="singleTop"
47+
android:launchMode="singleTask"
4248
android:theme="@style/Theme.ElementX.Splash"
4349
android:windowSoftInputMode="adjustResize">
4450
<intent-filter>
@@ -54,6 +60,9 @@
5460
android:host="open"
5561
android:scheme="elementx" />
5662
</intent-filter>
63+
<!--
64+
Oidc redirection
65+
-->
5766
<intent-filter>
5867
<action android:name="android.intent.action.VIEW" />
5968

@@ -80,6 +89,21 @@
8089
<!-- Matching asset file: https://staging.element.io/.well-known/assetlinks.json -->
8190
<data android:host="staging.element.io" />
8291
</intent-filter>
92+
<!--
93+
Element mobile links
94+
Example: https://mobile.element.io/element/?account_provider=example.org&login_hint=mxid:@alice:example.org
95+
-->
96+
<intent-filter android:autoVerify="true">
97+
<action android:name="android.intent.action.VIEW" />
98+
99+
<category android:name="android.intent.category.DEFAULT" />
100+
<category android:name="android.intent.category.BROWSABLE" />
101+
102+
<data android:scheme="https" />
103+
<!-- Matching asset file: https://mobile.element.io/.well-known/assetlinks.json -->
104+
<data android:host="mobile.element.io" />
105+
<data android:path="/element/" />
106+
</intent-filter>
83107
<!--
84108
matrix.to links
85109
Note: On Android 12 and higher clicking a web link (that is not an Android App Link) always shows content in a web browser

app/src/main/res/xml/backup_rules.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@
99
-->
1010
<full-backup-content>
1111
<exclude domain="root" path="." />
12+
<exclude domain="file" path="." />
13+
<exclude domain="database" path="." />
14+
<exclude domain="sharedpref" path="." />
15+
<exclude domain="external" path="."/>
1216
</full-backup-content>

app/src/main/res/xml/data_extraction_rules.xml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,18 @@
99
-->
1010
<data-extraction-rules>
1111
<cloud-backup>
12-
<exclude domain="root" path="." />
12+
<exclude domain="root" path="."/>
13+
<exclude domain="file" path="."/>
14+
<exclude domain="database" path="."/>
15+
<exclude domain="sharedpref" path="."/>
16+
<exclude domain="external" path="."/>
1317
</cloud-backup>
18+
1419
<device-transfer>
15-
<exclude domain="root" path="." />
20+
<exclude domain="root" path="."/>
21+
<exclude domain="file" path="."/>
22+
<exclude domain="database" path="."/>
23+
<exclude domain="sharedpref" path="."/>
24+
<exclude domain="external" path="."/>
1625
</device-transfer>
17-
</data-extraction-rules>
26+
</data-extraction-rules>

app/src/main/res/xml/locales_config.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<locale android:name="sv"/>
3131
<locale android:name="tr"/>
3232
<locale android:name="uk"/>
33+
<locale android:name="ur"/>
3334
<locale android:name="uz"/>
3435
<locale android:name="zh-CN"/>
3536
<locale android:name="zh-TW"/>

appnav/build.gradle.kts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,15 @@ dependencies {
5353
testImplementation(libs.molecule.runtime)
5454
testImplementation(libs.test.truth)
5555
testImplementation(libs.test.turbine)
56+
testImplementation(projects.features.login.test)
5657
testImplementation(projects.libraries.matrix.test)
57-
testImplementation(projects.libraries.oidc.impl)
58+
testImplementation(projects.libraries.oidc.test)
5859
testImplementation(projects.libraries.preferences.test)
5960
testImplementation(projects.libraries.push.test)
6061
testImplementation(projects.libraries.pushproviders.test)
6162
testImplementation(projects.features.networkmonitor.test)
62-
testImplementation(projects.features.login.impl)
6363
testImplementation(projects.tests.testutils)
6464
testImplementation(projects.features.rageshake.test)
65-
testImplementation(projects.features.rageshake.impl)
6665
testImplementation(projects.features.share.test)
6766
testImplementation(projects.services.appnavstate.test)
6867
testImplementation(projects.services.analytics.test)

appnav/src/main/kotlin/io/element/android/appnav/NotLoggedInFlowNode.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ import dagger.assisted.Assisted
2424
import dagger.assisted.AssistedInject
2525
import io.element.android.anvilannotations.ContributesNode
2626
import io.element.android.features.login.api.LoginEntryPoint
27+
import io.element.android.features.login.api.LoginParams
2728
import io.element.android.libraries.architecture.BackstackView
2829
import io.element.android.libraries.architecture.BaseFlowNode
30+
import io.element.android.libraries.architecture.NodeInputs
31+
import io.element.android.libraries.architecture.inputs
2932
import io.element.android.libraries.designsystem.utils.ForceOrientationInMobileDevices
3033
import io.element.android.libraries.designsystem.utils.ScreenOrientation
3134
import io.element.android.libraries.di.AppScope
@@ -46,10 +49,16 @@ class NotLoggedInFlowNode @AssistedInject constructor(
4649
buildContext = buildContext,
4750
plugins = plugins,
4851
) {
52+
data class Params(
53+
val loginParams: LoginParams?,
54+
) : NodeInputs
55+
4956
interface Callback : Plugin {
5057
fun onOpenBugReport()
5158
}
5259

60+
private val inputs = inputs<Params>()
61+
5362
override fun onBuilt() {
5463
super.onBuilt()
5564
lifecycle.subscribe(
@@ -74,6 +83,12 @@ class NotLoggedInFlowNode @AssistedInject constructor(
7483
}
7584
loginEntryPoint
7685
.nodeBuilder(this, buildContext)
86+
.params(
87+
LoginEntryPoint.Params(
88+
accountProvider = inputs.loginParams?.accountProvider,
89+
loginHint = inputs.loginParams?.loginHint,
90+
)
91+
)
7792
.callback(callback)
7893
.build()
7994
}

appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ import io.element.android.appnav.intent.ResolvedIntent
3333
import io.element.android.appnav.root.RootNavStateFlowFactory
3434
import io.element.android.appnav.root.RootPresenter
3535
import io.element.android.appnav.root.RootView
36+
import io.element.android.features.enterprise.api.EnterpriseService
37+
import io.element.android.features.login.api.LoginParams
3638
import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint
3739
import io.element.android.features.signedout.api.SignedOutEntryPoint
3840
import io.element.android.features.viewfolder.api.ViewFolderEntryPoint
3941
import io.element.android.libraries.architecture.BackstackView
4042
import io.element.android.libraries.architecture.BaseFlowNode
4143
import io.element.android.libraries.architecture.createNode
4244
import io.element.android.libraries.architecture.waitForChildAttached
45+
import io.element.android.libraries.core.uri.ensureProtocol
4346
import io.element.android.libraries.deeplink.DeeplinkData
4447
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
4548
import io.element.android.libraries.di.AppScope
@@ -61,6 +64,7 @@ class RootFlowNode @AssistedInject constructor(
6164
@Assisted val buildContext: BuildContext,
6265
@Assisted plugins: List<Plugin>,
6366
private val authenticationService: MatrixAuthenticationService,
67+
private val enterpriseService: EnterpriseService,
6468
private val navStateFlowFactory: RootNavStateFlowFactory,
6569
private val matrixSessionCache: MatrixSessionCache,
6670
private val presenter: RootPresenter,
@@ -99,14 +103,14 @@ class RootFlowNode @AssistedInject constructor(
99103
if (navState.loggedInState.isTokenValid) {
100104
tryToRestoreLatestSession(
101105
onSuccess = { sessionId -> switchToLoggedInFlow(sessionId, navState.cacheIndex) },
102-
onFailure = { switchToNotLoggedInFlow() }
106+
onFailure = { switchToNotLoggedInFlow(null) }
103107
)
104108
} else {
105109
switchToSignedOutFlow(SessionId(navState.loggedInState.sessionId))
106110
}
107111
}
108112
LoggedInState.NotLoggedIn -> {
109-
switchToNotLoggedInFlow()
113+
switchToNotLoggedInFlow(null)
110114
}
111115
}
112116
}
@@ -117,9 +121,9 @@ class RootFlowNode @AssistedInject constructor(
117121
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId, navId))
118122
}
119123

120-
private fun switchToNotLoggedInFlow() {
124+
private fun switchToNotLoggedInFlow(params: LoginParams?) {
121125
matrixSessionCache.removeAll()
122-
backstack.safeRoot(NavTarget.NotLoggedInFlow)
126+
backstack.safeRoot(NavTarget.NotLoggedInFlow(params))
123127
}
124128

125129
private fun switchToSignedOutFlow(sessionId: SessionId) {
@@ -175,7 +179,9 @@ class RootFlowNode @AssistedInject constructor(
175179
data object SplashScreen : NavTarget
176180

177181
@Parcelize
178-
data object NotLoggedInFlow : NavTarget
182+
data class NotLoggedInFlow(
183+
val params: LoginParams?
184+
) : NavTarget
179185

180186
@Parcelize
181187
data class LoggedInFlow(
@@ -211,13 +217,16 @@ class RootFlowNode @AssistedInject constructor(
211217
}
212218
createNode<LoggedInAppScopeFlowNode>(buildContext, plugins = listOf(inputs, callback))
213219
}
214-
NavTarget.NotLoggedInFlow -> {
220+
is NavTarget.NotLoggedInFlow -> {
215221
val callback = object : NotLoggedInFlowNode.Callback {
216222
override fun onOpenBugReport() {
217223
backstack.push(NavTarget.BugReport)
218224
}
219225
}
220-
createNode<NotLoggedInFlowNode>(buildContext, plugins = listOf(callback))
226+
val params = NotLoggedInFlowNode.Params(
227+
loginParams = navTarget.params,
228+
)
229+
createNode<NotLoggedInFlowNode>(buildContext, plugins = listOf(params, callback))
221230
}
222231
is NavTarget.SignedOutFlow -> {
223232
signedOutEntryPoint.nodeBuilder(this, buildContext)
@@ -272,18 +281,36 @@ class RootFlowNode @AssistedInject constructor(
272281
val resolvedIntent = intentResolver.resolve(intent) ?: return
273282
when (resolvedIntent) {
274283
is ResolvedIntent.Navigation -> navigateTo(resolvedIntent.deeplinkData)
284+
is ResolvedIntent.Login -> onLoginLink(resolvedIntent.params)
275285
is ResolvedIntent.Oidc -> onOidcAction(resolvedIntent.oidcAction)
276286
is ResolvedIntent.Permalink -> navigateTo(resolvedIntent.permalinkData)
277287
is ResolvedIntent.IncomingShare -> onIncomingShare(resolvedIntent.intent)
278288
}
279289
}
280290

291+
private suspend fun onLoginLink(params: LoginParams) {
292+
// Is there a session already?
293+
val latestSessionId = authenticationService.getLatestSessionId()
294+
if (latestSessionId == null) {
295+
// No session, open login
296+
if (enterpriseService.isAllowedToConnectToHomeserver(params.accountProvider.ensureProtocol())) {
297+
switchToNotLoggedInFlow(params)
298+
} else {
299+
Timber.w("Login link ignored, we are not allowed to connect to the homeserver")
300+
switchToNotLoggedInFlow(null)
301+
}
302+
} else {
303+
// Just ignore the login link if we already have a session
304+
Timber.w("Login link ignored, we already have a session")
305+
}
306+
}
307+
281308
private suspend fun onIncomingShare(intent: Intent) {
282309
// Is there a session already?
283310
val latestSessionId = authenticationService.getLatestSessionId()
284311
if (latestSessionId == null) {
285312
// No session, open login
286-
switchToNotLoggedInFlow()
313+
switchToNotLoggedInFlow(null)
287314
} else {
288315
attachSession(latestSessionId)
289316
.attachIncomingShare(intent)

0 commit comments

Comments
 (0)