Skip to content

Commit a69d126

Browse files
committed
Merge branch 'release/25.04.3' into main
2 parents dc05854 + 6879f88 commit a69d126

File tree

414 files changed

+4324
-1702
lines changed

Some content is hidden

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

414 files changed

+4324
-1702
lines changed

.github/workflows/danger.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- run: |
2121
npm install --save-dev @babel/plugin-transform-flow-strip-types
2222
- name: Danger
23-
uses: danger/danger-js@12.3.4
23+
uses: danger/danger-js@13.0.4
2424
with:
2525
args: "--dangerfile ./tools/danger/dangerfile.js"
2626
env:

.github/workflows/quality.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ jobs:
294294
yarn add danger-plugin-lint-report --dev
295295
- name: Danger lint
296296
if: always()
297-
uses: danger/danger-js@12.3.4
297+
uses: danger/danger-js@13.0.4
298298
with:
299299
args: "--dangerfile ./tools/danger/dangerfile-lint.js"
300300
env:

CONTRIBUTING.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<!--- TOC -->
44

5-
* [Contributing code to Matrix](#contributing-code-to-matrix)
65
* [Developer onboarding](#developer-onboarding)
6+
* [Contributing code to Matrix](#contributing-code-to-matrix)
77
* [Android Studio settings](#android-studio-settings)
88
* [Compilation](#compilation)
99
* [Strings](#strings)
@@ -28,17 +28,17 @@
2828

2929
<!--- END -->
3030

31-
## Contributing code to Matrix
31+
## Developer onboarding
3232

33-
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
33+
For a detailed overview of the project, see [Developer Onboarding](./docs/_developer_onboarding.md).
3434

35-
Element X Android support can be found in this room: [![Element X Android Matrix room #element-x-android:matrix.org](https://img.shields.io/matrix/element-x-android:matrix.org.svg?label=%23element-x-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-x-android:matrix.org).
35+
## Contributing code to Matrix
3636

37-
The rest of the document contains specific rules for Matrix Android projects
37+
If instead of contributing to the Element X Android project, you want to contribute to Synapse, the homeserver implementation, please read the [Synapse contribution guide](https://element-hq.github.io/synapse/latest/development/contributing_guide.html).
3838

39-
## Developer onboarding
39+
Element X Android support can be found in this room: [![Element X Android Matrix room #element-x-android:matrix.org](https://img.shields.io/matrix/element-x-android:matrix.org.svg?label=%23element-x-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-x-android:matrix.org).
4040

41-
For a detailed overview of the project, see [Developer Onboarding](./docs/_developer_onboarding.md).
41+
The rest of the document contains specific rules for Matrix Android projects.
4242

4343
## Android Studio settings
4444

app/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ licensee {
300300
allow("Apache-2.0")
301301
allow("MIT")
302302
allow("BSD-2-Clause")
303+
allow("BSD-3-Clause")
303304
allowUrl("https://opensource.org/licenses/MIT")
304305
allowUrl("https://developer.android.com/studio/terms.html")
305306
allowUrl("https://www.zetetic.net/sqlcipher/license/")

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

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<locale android:name="be"/>
44
<locale android:name="bg"/>
55
<locale android:name="cs"/>
6+
<locale android:name="cy"/>
67
<locale android:name="de"/>
78
<locale android:name="el"/>
89
<locale android:name="en"/>
@@ -17,6 +18,7 @@
1718
<locale android:name="in"/>
1819
<locale android:name="it"/>
1920
<locale android:name="ka"/>
21+
<locale android:name="lt"/>
2022
<locale android:name="nb"/>
2123
<locale android:name="nl"/>
2224
<locale android:name="pl"/>

appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt

+11-5
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,21 @@ class SyncOrchestrator @AssistedInject constructor(
7878
internal fun observeStates() = coroutineScope.launch {
7979
Timber.tag(tag).d("start observing the app and network state")
8080

81+
val isAppActiveFlow = combine(
82+
appForegroundStateService.isInForeground,
83+
appForegroundStateService.isInCall,
84+
appForegroundStateService.isSyncingNotificationEvent,
85+
appForegroundStateService.hasRingingCall,
86+
) { isInForeground, isInCall, isSyncingNotificationEvent, hasRingingCall ->
87+
isInForeground || isInCall || isSyncingNotificationEvent || hasRingingCall
88+
}
89+
8190
combine(
8291
// small debounce to avoid spamming startSync when the state is changing quickly in case of error.
8392
syncService.syncState.debounce(100.milliseconds),
8493
networkMonitor.connectivity,
85-
appForegroundStateService.isInForeground,
86-
appForegroundStateService.isInCall,
87-
appForegroundStateService.isSyncingNotificationEvent,
88-
) { syncState, networkState, isInForeground, isInCall, isSyncingNotificationEvent ->
89-
val isAppActive = isInForeground || isInCall || isSyncingNotificationEvent
94+
isAppActiveFlow,
95+
) { syncState, networkState, isAppActive ->
9096
val isNetworkAvailable = networkState == NetworkStatus.Connected
9197

9298
Timber.tag(tag).d("isAppActive=$isAppActive, isNetworkAvailable=$isNetworkAvailable")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<string name="banner_migrate_to_native_sliding_sync_action">"Allgofnodi ac Uwchraddio"</string>
4+
<string name="banner_migrate_to_native_sliding_sync_app_force_logout_title">"Nid yw %1$s bellach yn cefnogi\'r hen brotocol. Allgofnodwch a mewngofnodi\'n ôl i barhau i ddefnyddio\'r ap."</string>
5+
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Nid yw eich gweinydd cartref yn cefnogi\'r hen brotocol mwyach. Allgofnodwch a mewngofnodwch yn ôl i barhau i ddefnyddio\'r ap."</string>
6+
</resources>
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
33
<string name="banner_migrate_to_native_sliding_sync_action">"Logg ut og oppgrader"</string>
4+
<string name="banner_migrate_to_native_sliding_sync_app_force_logout_title">"%1$s støtter ikke lenger den gamle protokollen. Logg ut og logg inn igjen for å fortsette å bruke appen."</string>
45
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Hjemmeserveren din støtter ikke lenger den gamle protokollen. Vennligst logg ut og inn igjen for å fortsette å bruke appen."</string>
56
</resources>

appnav/src/test/kotlin/io/element/android/appnav/SyncOrchestratorTest.kt

+44
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,50 @@ class SyncOrchestratorTest {
236236
stopSyncRecorder.assertions().isCalledOnce()
237237
}
238238

239+
@Test
240+
fun `when the app was in background and we have an incoming ringing call, a sync will be started`() = runTest {
241+
val startSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
242+
val stopSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
243+
val syncService = FakeSyncService(initialSyncState = SyncState.Idle).apply {
244+
startSyncLambda = startSyncRecorder
245+
stopSyncLambda = stopSyncRecorder
246+
}
247+
val networkMonitor = FakeNetworkMonitor(initialStatus = NetworkStatus.Connected)
248+
val appForegroundStateService = FakeAppForegroundStateService(
249+
initialForegroundValue = false,
250+
initialIsSyncingNotificationEventValue = false,
251+
initialHasRingingCall = false,
252+
)
253+
val syncOrchestrator = createSyncOrchestrator(
254+
syncService = syncService,
255+
networkMonitor = networkMonitor,
256+
appForegroundStateService = appForegroundStateService,
257+
)
258+
259+
// We start observing
260+
syncOrchestrator.observeStates()
261+
262+
// Advance the time to make sure the orchestrator has had time to start processing the inputs
263+
advanceTimeBy(100.milliseconds)
264+
265+
// Start sync was never called
266+
startSyncRecorder.assertions().isNeverCalled()
267+
268+
// Now we receive a ringing call
269+
appForegroundStateService.updateHasRingingCall(true)
270+
271+
// Start sync will be called shortly after
272+
advanceTimeBy(1.milliseconds)
273+
startSyncRecorder.assertions().isCalledOnce()
274+
275+
// If the sync is running and the ringing call notification is now over, the sync stops after a delay
276+
syncService.emitSyncState(SyncState.Running)
277+
appForegroundStateService.updateHasRingingCall(false)
278+
279+
advanceTimeBy(10.seconds)
280+
stopSyncRecorder.assertions().isCalledOnce()
281+
}
282+
239283
@Test
240284
fun `when the app is in foreground, we sync for a notification and a call is ongoing, the sync will only stop when all conditions are false`() = runTest {
241285
val startSyncRecorder = lambdaRecorder<Result<Unit>> { Result.success(Unit) }

docs/_developer_onboarding.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* [Sync](#sync)
1111
* [Rust SDK](#rust-sdk)
1212
* [Matrix Rust Component Kotlin](#matrix-rust-component-kotlin)
13-
* [Build the SDK locally](#build-the-sdk-locally)
13+
* [Building the SDK locally](#building-the-sdk-locally)
1414
* [The Android project](#the-android-project)
1515
* [Application](#application)
1616
* [Jetpack Compose](#jetpack-compose)
@@ -107,15 +107,17 @@ This is the goal of https://github.com/matrix-org/matrix-rust-components-kotlin.
107107
This repository is used for distributing kotlin releases of the Matrix Rust SDK.
108108
It'll provide the corresponding aar and also publish them on maven.
109109

110-
Most of the time you want to use the releases made on maven with gradle:
110+
Most of the time **you want to use the releases made on maven with gradle**:
111111

112112
```groovy
113113
implementation("org.matrix.rustcomponents:sdk-android:latest-version")
114114
```
115115

116116
You can also have access to the aars through the [release](https://github.com/matrix-org/matrix-rust-components-kotlin/releases) page.
117117

118-
#### Build the SDK locally
118+
#### Building the SDK locally
119+
120+
If you want to make changes to the SDK or test them before integrating it with your codebase, you can build the SDK locally too.
119121

120122
Prerequisites:
121123
* Install the Android NDK (Native Development Kit). To do this from within

enterprise

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Main changes in this version: bug fixes and improvements.
2+
Full changelog: https://github.com/element-hq/element-x-android/releases
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<string name="screen_analytics_settings_read_terms_content_link">"yma"</string>
4+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<string name="screen_analytics_settings_help_us_improve">"Dalinkitės anoniminiais naudojimo duomenimis ir padėkite mums nustatyti problemas."</string>
4+
<string name="screen_analytics_settings_read_terms">"Galite perskaityti visas mūsų sąlygas %1$s ."</string>
5+
<string name="screen_analytics_settings_read_terms_content_link">"čia"</string>
6+
<string name="screen_analytics_settings_share_data">"Dalytis analitiniais duomenimis"</string>
7+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<string name="screen_analytics_prompt_read_terms_content_link">"yma"</string>
4+
</resources>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<string name="screen_analytics_prompt_data_usage">"Mes nekaupsime ir neprofiliuosime jokių asmens duomenų"</string>
4+
<string name="screen_analytics_prompt_help_us_improve">"Dalinkitės anoniminiais naudojimo duomenimis ir padėkite mums nustatyti problemas."</string>
5+
<string name="screen_analytics_prompt_read_terms">"Galite perskaityti visas mūsų sąlygas %1$s ."</string>
6+
<string name="screen_analytics_prompt_read_terms_content_link">"čia"</string>
7+
<string name="screen_analytics_prompt_settings">"Tai galite bet kada išjungti"</string>
8+
<string name="screen_analytics_prompt_third_party_sharing">"Mes nesidalinsime Jūsų duomenimis su trečiosiomis šalimis"</string>
9+
<string name="screen_analytics_prompt_title">"Padėkite pagerinti %1$s"</string>
10+
</resources>

features/call/impl/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ dependencies {
6666
implementation(projects.appconfig)
6767
implementation(projects.features.enterprise.api)
6868
implementation(projects.libraries.architecture)
69+
implementation(projects.libraries.androidutils)
6970
implementation(projects.libraries.core)
7071
implementation(projects.libraries.designsystem)
7172
implementation(projects.libraries.featureflag.api)

features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt

+42
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
package io.element.android.features.call.impl.ui
99

1010
import android.annotation.SuppressLint
11+
import android.content.Context
12+
import android.media.AudioDeviceCallback
13+
import android.media.AudioDeviceInfo
14+
import android.media.AudioManager
1115
import android.util.Log
1216
import android.view.ViewGroup
1317
import android.webkit.ConsoleMessage
@@ -21,12 +25,17 @@ import androidx.compose.foundation.layout.fillMaxSize
2125
import androidx.compose.foundation.layout.padding
2226
import androidx.compose.material3.ExperimentalMaterial3Api
2327
import androidx.compose.runtime.Composable
28+
import androidx.compose.runtime.getValue
29+
import androidx.compose.runtime.mutableStateOf
30+
import androidx.compose.runtime.remember
31+
import androidx.compose.runtime.setValue
2432
import androidx.compose.ui.Alignment
2533
import androidx.compose.ui.Modifier
2634
import androidx.compose.ui.platform.LocalInspectionMode
2735
import androidx.compose.ui.res.stringResource
2836
import androidx.compose.ui.tooling.preview.PreviewParameter
2937
import androidx.compose.ui.viewinterop.AndroidView
38+
import androidx.core.content.getSystemService
3039
import io.element.android.compound.tokens.generated.CompoundIcons
3140
import io.element.android.features.call.impl.R
3241
import io.element.android.features.call.impl.pip.PictureInPictureEvents
@@ -35,6 +44,8 @@ import io.element.android.features.call.impl.pip.PictureInPictureStateProvider
3544
import io.element.android.features.call.impl.pip.aPictureInPictureState
3645
import io.element.android.features.call.impl.utils.WebViewPipController
3746
import io.element.android.features.call.impl.utils.WebViewWidgetMessageInterceptor
47+
import io.element.android.libraries.androidutils.compat.disableExternalAudioDevice
48+
import io.element.android.libraries.androidutils.compat.enableExternalAudioDevice
3849
import io.element.android.libraries.architecture.AsyncData
3950
import io.element.android.libraries.designsystem.components.ProgressDialog
4051
import io.element.android.libraries.designsystem.components.button.BackButton
@@ -147,9 +158,11 @@ private fun CallWebView(
147158
Text("WebView - can't be previewed")
148159
}
149160
} else {
161+
var audioDeviceCallback: AudioDeviceCallback? by remember { mutableStateOf(null) }
150162
AndroidView(
151163
modifier = modifier,
152164
factory = { context ->
165+
audioDeviceCallback = context.setupAudioConfiguration()
153166
WebView(context).apply {
154167
onWebViewCreate(this)
155168
setup(userAgent, onPermissionsRequest)
@@ -161,12 +174,41 @@ private fun CallWebView(
161174
}
162175
},
163176
onRelease = { webView ->
177+
// Reset audio mode
178+
webView.context.releaseAudioConfiguration(audioDeviceCallback)
164179
webView.destroy()
165180
}
166181
)
167182
}
168183
}
169184

185+
private fun Context.setupAudioConfiguration(): AudioDeviceCallback? {
186+
val audioManager = getSystemService<AudioManager>() ?: return null
187+
// Set 'voice call' mode so volume keys actually control the call volume
188+
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
189+
audioManager.enableExternalAudioDevice()
190+
return object : AudioDeviceCallback() {
191+
override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
192+
Timber.d("Audio devices added")
193+
audioManager.enableExternalAudioDevice()
194+
}
195+
196+
override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
197+
Timber.d("Audio devices removed")
198+
audioManager.enableExternalAudioDevice()
199+
}
200+
}.also {
201+
audioManager.registerAudioDeviceCallback(it, null)
202+
}
203+
}
204+
205+
private fun Context.releaseAudioConfiguration(audioDeviceCallback: AudioDeviceCallback?) {
206+
val audioManager = getSystemService<AudioManager>() ?: return
207+
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
208+
audioManager.disableExternalAudioDevice()
209+
audioManager.mode = AudioManager.MODE_NORMAL
210+
}
211+
170212
@SuppressLint("SetJavaScriptEnabled")
171213
private fun WebView.setup(
172214
userAgent: String,

0 commit comments

Comments
 (0)