Skip to content

Commit 159a478

Browse files
committed
Merge branch 'release/0.7.1' into main
2 parents 8806275 + 69fb15b commit 159a478

File tree

1,017 files changed

+5706
-4009
lines changed

Some content is hidden

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

1,017 files changed

+5706
-4009
lines changed

.github/workflows/maestro.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
uses: actions/download-artifact@v4
8080
with:
8181
name: elementx-apk-maestro
82-
- uses: mobile-dev-inc/[email protected].1
82+
- uses: mobile-dev-inc/[email protected].2
8383
if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch'
8484
with:
8585
api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}

CHANGES.md

+25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
Changes in Element X v0.7.0 (2024-10-10)
2+
========================================
3+
4+
## What's Changed
5+
### 🙌 Improvements
6+
* Enable Login with QR code in release builds. by @bmarty in https://github.com/element-hq/element-x-android/pull/3646
7+
* Remove unused `RoomSummary` cache by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3647
8+
### 🐛 Bugfixes
9+
* Add the `CallWebView` logs to our logging stack by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3637
10+
### Dependency upgrades
11+
* Update dependency io.element.android:emojibase-bindings to v1.3.3 by @renovate in https://github.com/element-hq/element-x-android/pull/3620
12+
* fix(deps): update dependency androidx.compose:compose-bom to v2024.09.03 by @renovate in https://github.com/element-hq/element-x-android/pull/3583
13+
* fix(deps): update dependency io.mockk:mockk to v1.13.13 by @renovate in https://github.com/element-hq/element-x-android/pull/3634
14+
* chore(deps): update dependencyanalysis to v2.1.4 by @renovate in https://github.com/element-hq/element-x-android/pull/3610
15+
* fix(deps): update dependency androidx.webkit:webkit to v1.12.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3584
16+
* fix(deps): update dependency com.posthog:posthog-android to v3.8.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3638
17+
* Upgrade Kotlin to v2.0 by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3594
18+
### Others
19+
* Rework room summary by @ganfra in https://github.com/element-hq/element-x-android/pull/3631
20+
* QrCode intro screen: add subtitle and fix button wording #3632 by @bmarty in https://github.com/element-hq/element-x-android/pull/3633
21+
* Improve avatar rendering by @ganfra in https://github.com/element-hq/element-x-android/pull/3642
22+
* Add feature flag IdentityPinningViolationNotifications. by @bmarty in https://github.com/element-hq/element-x-android/pull/3648
23+
* Crypto copy adjustment by @bmarty in https://github.com/element-hq/element-x-android/pull/3649
24+
25+
126
Changes in Element X v0.6.5 (2024-10-09)
227
========================================
328

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3-
<string name="banner_migrate_to_native_sliding_sync_action">"Αποσύνδεση &amp;amp; Αναβάθμιση"</string>
3+
<string name="banner_migrate_to_native_sliding_sync_action">"Αποσύνδεση &amp; Αναβάθμιση"</string>
44
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Ο οικιακός διακομιστής σου δεν υποστηρίζει πλέον το παλιό πρωτόκολλο. Αποσυνδέσου και συνδέσου ξανά για να συνεχίσεις να χρησιμοποιείς την εφαρμογή."</string>
55
</resources>
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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">"Выйти и обновить"</string>
4-
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Ваш homeserver больше не поддерживает старый протокол. Пожалуйста, выйдите из системы и войдите снова, чтобы продолжить использование приложения."</string>
4+
<string name="banner_migrate_to_native_sliding_sync_force_logout_title">"Ваш домашний сервер больше не поддерживает старый протокол. Пожалуйста, выйдите и войдите в свою учётную запись снова, чтобы продолжить использование приложения."</string>
55
</resources>

build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ allprojects {
4949
config.from(files("$rootDir/tools/detekt/detekt.yml"))
5050
}
5151
dependencies {
52-
detektPlugins("io.nlopez.compose.rules:detekt:0.4.15")
52+
detektPlugins("io.nlopez.compose.rules:detekt:0.4.16")
5353
}
5454

5555
// KtLint
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Main changes in this version: bug fixes and performance improvement.
2+
Full changelog: https://github.com/element-hq/element-x-android/releases

fastlane/metadata/android/en-US/full_description.txt

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Element X brings you both sovereign & seamless collaboration built on Matrix.
22

33
The collaboration capabilities include chat & video calls with the modern set of features such as:
44
• public & private channels
5-
• room moderation & access conUpdatetrol
5+
• room moderation & access control
66
• replies, reactions, polls, read receipts, pinned messages, etc.
77
• simultaneous chat & calls (picture in picture)
88
• decentralized & federated communication across organizations
@@ -32,4 +32,8 @@ Enjoy the freedom of the Matrix open standard! You have native interoperability
3232
Enjoy your right to private conversations - free from data mining, ads and all the rest of it - and stay secure. Only the people in your conversation can read your messages.
3333

3434
<b>Chat across multiple devices</b>
35-
Stay in touch wherever you are with fully synchronized message history across all your devices, even those running Element legacy app, and on the web at https://app.element.io
35+
Stay in touch wherever you are with fully synchronized message history across all your devices, even those running Element legacy app, and on the web at https://app.element.io
36+
37+
The application requires the android.permission.REQUEST_INSTALL_PACKAGES permission to enable the installation of applications received as attachments, ensuring seamless and convenient access to new software within the app.
38+
39+
The application requires the USE_FULL_SCREEN_INTENT permission to ensure our users can effectively receive call notifications even when their devices are locked.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3-
<string name="screen_analytics_settings_help_us_improve">"Предоставлять анонимные данные об использовании, чтобы помочь нам выявить проблемы."</string>
3+
<string name="screen_analytics_settings_help_us_improve">"Предоставьте разработчикам анонимные данные об использовании, чтобы помочь им выявлять проблемы эффективнее."</string>
44
<string name="screen_analytics_settings_read_terms">"Вы можете ознакомиться со всеми нашими условиями %1$s."</string>
55
<string name="screen_analytics_settings_read_terms_content_link">"здесь"</string>
6-
<string name="screen_analytics_settings_share_data">"Делитесь данными аналитики"</string>
6+
<string name="screen_analytics_settings_share_data">"Отправлять аналитические данные"</string>
77
</resources>

features/analytics/impl/src/main/res/values-pt/translations.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<string name="screen_analytics_prompt_help_us_improve">"Partilhe dados de utilização anónimos para nos ajudar a identificar problemas."</string>
55
<string name="screen_analytics_prompt_read_terms">"Podes ler todos os nossos termos %1$s."</string>
66
<string name="screen_analytics_prompt_read_terms_content_link">"aqui"</string>
7-
<string name="screen_analytics_prompt_settings">"Podes desligar qualquer momento"</string>
7+
<string name="screen_analytics_prompt_settings">"Pode desactivar a qualquer momento"</string>
88
<string name="screen_analytics_prompt_third_party_sharing">"Não partilharemos os teus dados com terceiros"</string>
99
<string name="screen_analytics_prompt_title">"Ajude a melhorar a %1$s"</string>
1010
</resources>

features/analytics/impl/src/main/res/values-ru/translations.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
33
<string name="screen_analytics_prompt_data_usage">"Мы не будем записывать или профилировать какие-либо персональные данные"</string>
4-
<string name="screen_analytics_prompt_help_us_improve">"Предоставлять анонимные данные об использовании, чтобы помочь нам выявить проблемы."</string>
4+
<string name="screen_analytics_prompt_help_us_improve">"Предоставьте разработчикам анонимные данные об использовании, чтобы помочь им выявлять проблемы эффективнее."</string>
55
<string name="screen_analytics_prompt_read_terms">"Вы можете ознакомиться со всеми нашими условиями %1$s."</string>
66
<string name="screen_analytics_prompt_read_terms_content_link">"здесь"</string>
77
<string name="screen_analytics_prompt_settings">"Вы можете отключить эту функцию в любое время"</string>

features/call/impl/src/main/AndroidManifest.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121

2222
<!-- Permissions for call foreground services -->
2323
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
24-
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
25-
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
24+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
25+
2626
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
2727

2828
<application>
@@ -80,7 +80,7 @@
8080
android:name=".services.CallForegroundService"
8181
android:enabled="true"
8282
android:exported="false"
83-
android:foregroundServiceType="phoneCall" />
83+
android:foregroundServiceType="microphone" />
8484

8585
<receiver
8686
android:name=".receivers.DeclineCallBroadcastReceiver"

features/call/impl/src/main/kotlin/io/element/android/features/call/impl/services/CallForegroundService.kt

+10-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
package io.element.android.features.call.impl.services
99

10+
import android.Manifest
1011
import android.app.Service
1112
import android.content.Context
1213
import android.content.Intent
14+
import android.content.pm.PackageManager
1315
import android.content.pm.ServiceInfo
1416
import android.os.Build
1517
import android.os.IBinder
@@ -33,8 +35,12 @@ import timber.log.Timber
3335
class CallForegroundService : Service() {
3436
companion object {
3537
fun start(context: Context) {
36-
val intent = Intent(context, CallForegroundService::class.java)
37-
ContextCompat.startForegroundService(context, intent)
38+
if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
39+
val intent = Intent(context, CallForegroundService::class.java)
40+
ContextCompat.startForegroundService(context, intent)
41+
} else {
42+
Timber.w("Microphone permission is not granted, cannot start the call foreground service")
43+
}
3844
}
3945

4046
fun stop(context: Context) {
@@ -67,8 +73,8 @@ class CallForegroundService : Service() {
6773
.setContentIntent(pendingIntent)
6874
.build()
6975
val notificationId = NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.ONGOING_CALL)
70-
val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
71-
ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL
76+
val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
77+
ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
7278
} else {
7379
0
7480
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class CallScreenPresenter @AssistedInject constructor(
180180
urlState = urlState.value,
181181
webViewError = webViewError,
182182
userAgent = userAgent,
183+
isCallActive = isJoinedCall,
183184
isInWidgetMode = isInWidgetMode,
184185
eventSink = { handleEvents(it) },
185186
)

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

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ data class CallScreenState(
1313
val urlState: AsyncData<String>,
1414
val webViewError: String?,
1515
val userAgent: String,
16+
val isCallActive: Boolean,
1617
val isInWidgetMode: Boolean,
1718
val eventSink: (CallScreenEvents) -> Unit,
1819
)

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

+2
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ internal fun aCallScreenState(
2424
urlState: AsyncData<String> = AsyncData.Success("https://call.element.io/some-actual-call?with=parameters"),
2525
webViewError: String? = null,
2626
userAgent: String = "",
27+
isCallActive: Boolean = true,
2728
isInWidgetMode: Boolean = false,
2829
eventSink: (CallScreenEvents) -> Unit = {},
2930
): CallScreenState {
3031
return CallScreenState(
3132
urlState = urlState,
3233
webViewError = webViewError,
3334
userAgent = userAgent,
35+
isCallActive = isCallActive,
3436
isInWidgetMode = isInWidgetMode,
3537
eventSink = eventSink,
3638
)

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

+15-17
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import androidx.annotation.RequiresApi
2626
import androidx.appcompat.app.AppCompatActivity
2727
import androidx.compose.runtime.Composable
2828
import androidx.compose.runtime.DisposableEffect
29+
import androidx.compose.runtime.LaunchedEffect
2930
import androidx.compose.runtime.getValue
3031
import androidx.compose.runtime.mutableStateOf
3132
import androidx.compose.runtime.rememberUpdatedState
@@ -95,14 +96,19 @@ class ElementCallActivity :
9596
pictureInPicturePresenter.setPipView(this)
9697

9798
audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
98-
requestAudioFocus()
9999

100100
setContent {
101101
val pipState = pictureInPicturePresenter.present()
102102
ListenToAndroidEvents(pipState)
103103
ElementThemeApp(appPreferencesStore) {
104104
val state = presenter.present()
105105
eventSink = state.eventSink
106+
LaunchedEffect(state.isCallActive, state.isInWidgetMode) {
107+
// Note when not in WidgetMode, isCallActive will never be true, so consider the call is active
108+
if (state.isCallActive || !state.isInWidgetMode) {
109+
setCallIsActive()
110+
}
111+
}
106112
CallScreenView(
107113
state = state,
108114
pipState = pipState,
@@ -115,6 +121,11 @@ class ElementCallActivity :
115121
}
116122
}
117123

124+
private fun setCallIsActive() {
125+
requestAudioFocus()
126+
CallForegroundService.start(this)
127+
}
128+
118129
@Composable
119130
private fun ListenToAndroidEvents(pipState: PictureInPictureState) {
120131
val pipEventSink by rememberUpdatedState(pipState.eventSink)
@@ -156,18 +167,6 @@ class ElementCallActivity :
156167
setCallType(intent)
157168
}
158169

159-
override fun onStart() {
160-
super.onStart()
161-
CallForegroundService.stop(this)
162-
}
163-
164-
override fun onStop() {
165-
super.onStop()
166-
if (!isFinishing && !isChangingConfigurations) {
167-
CallForegroundService.start(this)
168-
}
169-
}
170-
171170
override fun onDestroy() {
172171
super.onDestroy()
173172
releaseAudioFocus()
@@ -231,10 +230,10 @@ class ElementCallActivity :
231230

232231
@Suppress("DEPRECATION")
233232
private fun requestAudioFocus() {
234-
val audioAttributes = AudioAttributes.Builder()
235-
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
236-
.build()
237233
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
234+
val audioAttributes = AudioAttributes.Builder()
235+
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
236+
.build()
238237
val request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
239238
.setAudioAttributes(audioAttributes)
240239
.build()
@@ -247,7 +246,6 @@ class ElementCallActivity :
247246
AudioManager.STREAM_VOICE_CALL,
248247
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE,
249248
)
250-
251249
audioFocusChangeListener = listener
252250
}
253251
}

features/call/impl/src/main/res/values-nl/translations.xml

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
<string name="call_foreground_service_channel_title_android">"Actieve oproep"</string>
44
<string name="call_foreground_service_message_android">"Tik om terug te gaan naar het gesprek"</string>
55
<string name="call_foreground_service_title_android">"☎️ In gesprek"</string>
6+
<string name="screen_incoming_call_subtitle_android">"Inkomende Element-oproep"</string>
67
</resources>

features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenPresenterTest.kt

+40
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class CallScreenPresenterTest {
7373
assertThat(initialState.urlState).isEqualTo(AsyncData.Success("https://call.element.io"))
7474
assertThat(initialState.webViewError).isNull()
7575
assertThat(initialState.isInWidgetMode).isFalse()
76+
assertThat(initialState.isCallActive).isFalse()
7677
analyticsLambda.assertions().isNeverCalled()
7778
joinedCallLambda.assertions().isCalledOnce()
7879
}
@@ -106,6 +107,7 @@ class CallScreenPresenterTest {
106107
joinedCallLambda.assertions().isCalledOnce()
107108
val initialState = awaitItem()
108109
assertThat(initialState.urlState).isInstanceOf(AsyncData.Success::class.java)
110+
assertThat(initialState.isCallActive).isFalse()
109111
assertThat(initialState.isInWidgetMode).isTrue()
110112
assertThat(widgetProvider.getWidgetCalled).isTrue()
111113
assertThat(widgetDriver.runCalledCount).isEqualTo(1)
@@ -203,6 +205,44 @@ class CallScreenPresenterTest {
203205
}
204206
}
205207

208+
@Test
209+
fun `present - a received room member message makes the call to be active`() = runTest {
210+
val navigator = FakeCallScreenNavigator()
211+
val widgetDriver = FakeMatrixWidgetDriver()
212+
val presenter = createCallScreenPresenter(
213+
callType = CallType.RoomCall(A_SESSION_ID, A_ROOM_ID),
214+
widgetDriver = widgetDriver,
215+
navigator = navigator,
216+
dispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
217+
screenTracker = FakeScreenTracker {},
218+
)
219+
val messageInterceptor = FakeWidgetMessageInterceptor()
220+
moleculeFlow(RecompositionMode.Immediate) {
221+
presenter.present()
222+
}.test {
223+
skipItems(1)
224+
val initialState = awaitItem()
225+
assertThat(initialState.isCallActive).isFalse()
226+
initialState.eventSink(CallScreenEvents.SetupMessageChannels(messageInterceptor))
227+
messageInterceptor.givenInterceptedMessage(
228+
"""
229+
{
230+
"action":"send_event",
231+
"api":"fromWidget",
232+
"widgetId":"1",
233+
"requestId":"1",
234+
"data":{
235+
"type":"org.matrix.msc3401.call.member"
236+
}
237+
}
238+
""".trimIndent()
239+
)
240+
skipItems(1)
241+
val finalState = awaitItem()
242+
assertThat(finalState.isCallActive).isTrue()
243+
}
244+
}
245+
206246
@Test
207247
fun `present - automatically starts the Matrix client sync when on RoomCall`() = runTest {
208248
val navigator = FakeCallScreenNavigator()

0 commit comments

Comments
 (0)