diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9b4a5e3689..f0c8fd1e6f 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Check membership if: github.event.pull_request.user.login != 'renovate[bot]' - uses: tspascoal/get-user-teams-membership@b1480b119326dde04ceffbeccd98e41892539c74 # v4.0.0 + uses: tspascoal/get-user-teams-membership@818140d631d5f29f26b151afbe4179f87d9ceb5e # v4.0.1 id: teams with: username: ${{ github.event.pull_request.user.login }} diff --git a/.github/workflows/triage-incoming.yml b/.github/workflows/triage-incoming.yml index 8e8d03c9c4..b93ea81403 100644 --- a/.github/workflows/triage-incoming.yml +++ b/.github/workflows/triage-incoming.yml @@ -10,7 +10,7 @@ jobs: triage-new-issues: runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/91 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml index 3ec20f332b..0b587369ed 100644 --- a/.github/workflows/triage-labelled.yml +++ b/.github/workflows/triage-labelled.yml @@ -14,7 +14,7 @@ jobs: if: > github.repository == 'element-hq/element-x-android' steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/43 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -23,7 +23,7 @@ jobs: name: Move triaged needs info issues on board runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 id: addItem with: project-url: https://github.com/orgs/element-hq/projects/91 @@ -47,7 +47,7 @@ jobs: if: > contains(github.event.issue.labels.*.name, 'Team: Element X Feature') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/73 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -58,7 +58,7 @@ jobs: if: > contains(github.event.issue.labels.*.name, 'Team: Verticals Feature') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/57 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -70,7 +70,7 @@ jobs: contains(github.event.issue.labels.*.name, 'Team: QA') || contains(github.event.issue.labels.*.name, 'X-Needs-Signoff') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/69 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} @@ -81,7 +81,7 @@ jobs: if: > contains(github.event.issue.labels.*.name, 'X-Needs-Signoff') steps: - - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2 with: project-url: https://github.com/orgs/element-hq/projects/89 github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/CHANGES.md b/CHANGES.md index df109d34a6..a57395b833 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,88 @@ +Changes in Element X v26.05.0 +============================= + + + +## What's Changed +### ✨ Features +* Add flag for automatic back pagination feature by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6637 +* Promote "history sharing on invite" out of developer options by @richvdh in https://github.com/element-hq/element-x-android/pull/6647 +* Remove RoomDirectorySearch feature flag — always enable the feature by @Copilot in https://github.com/element-hq/element-x-android/pull/6736 +### 🙌 Improvements +* Change native back button behavior in EC view (close settings in EC with os native back) by @toger5 in https://github.com/element-hq/element-x-android/pull/6642 +* Revert PR #6642 by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6724 +* Use 'Report a problem' string instead of 'Report bug' by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6735 +### 🐛 Bugfixes +* Remove distributed tracing of the 'timeline loading' flow by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6644 +* Set max lines for 'in reply to' view conditionally by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6612 +* Mention pill cut off by @bmarty in https://github.com/element-hq/element-x-android/pull/6651 +* Ensure that bottom sheet can scroll by @bmarty in https://github.com/element-hq/element-x-android/pull/6661 +* Remove legacy `mx-reply` from `toPlainText` formatted event contents by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6683 +* Fix ANRs when receiving push notifications by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6696 +* Mitigate a deadlock when loading room timelines by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6674 +* Fix calls on Huawei devices: skip addWebMessageListener on Chromium < 119 by @manfrommedan in https://github.com/element-hq/element-x-android/pull/6640 +* Allow cancelling room loading in Home screen by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6723 +* Let our Json parser accept comments and trailing comma. by @bmarty in https://github.com/element-hq/element-x-android/pull/6700 +* Fix low width image message by @krbns in https://github.com/element-hq/element-x-android/pull/6692 +* Make icons in the Chat screen top bar 16dp by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6733 +* Fix back button sometimes not working after exiting a thread by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6732 +* Make send event state UI easier to click by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6739 +### 🗣 Translations +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6658 +* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/6716 +### 🧱 Build +* Fix record screenshots action permissions by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6679 +* Fix dependency error by @bmarty in https://github.com/element-hq/element-x-android/pull/6697 +### 🚧 In development 🚧 +* [Link new device] Add missing screen to render digits that the user has to type on the other device by @bmarty in https://github.com/element-hq/element-x-android/pull/6680 +### Dependency upgrades +* Update dependency io.nlopez.compose.rules:detekt to v0.5.7 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6594 +* Update zizmorcore/zizmor-action action to v0.5.3 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6630 +* Update dependency io.sentry:sentry-android to v8.38.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6597 +* fix(deps): update camera to v1.6.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6514 +* Update dependency io.sentry:sentry-android to v8.39.1 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6648 +* Update dependency io.element.android:element-call-embedded to v0.19.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6662 +* Update dependencyAnalysis to v3.9.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6657 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.04.27 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6666 +* Update dependency io.sentry:sentry-android to v8.40.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6691 +* Update dependency org.jsoup:jsoup to v1.22.2 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6660 +* Update kotlin by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6687 +* Update dependency androidx.compose:compose-bom to v2026.04.01 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6693 +* Update dependency io.nlopez.compose.rules:detekt to v0.5.8 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6711 +* Update dependency com.posthog:posthog-android to v3.43.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6704 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6718 +* Update roborazzi to v1.60.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6722 +* Update dependency net.zetetic:sqlcipher-android to v4.15.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6727 +* Update dependency org.maplibre.gl:android-sdk to v13.1.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6731 +* Update dependency org.matrix.rustcomponents:sdk-android to v26.05.6 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6734 +* Update dependencyAnalysis to v3.10.0 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6742 +* Update tspascoal/get-user-teams-membership action to v4 by @renovate[bot] in https://github.com/element-hq/element-x-android/pull/6747 +### Others +* devx: fix build sdk script options for macos by @BillCarsonFr in https://github.com/element-hq/element-x-android/pull/6636 +* PR:Fix mention pill cut off by @krbns in https://github.com/element-hq/element-x-android/pull/6622 +* Update media viewer UI by @bmarty in https://github.com/element-hq/element-x-android/pull/6643 +* Strip formatting from media captions in room summary by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6670 +* Update error mappings for Link new device flow by @hughns in https://github.com/element-hq/element-x-android/pull/6677 +* Rename `OIDC` components and variables to `OAuth` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/6686 +* [Link new device] Add missing error case "already signed in" by @bmarty in https://github.com/element-hq/element-x-android/pull/6688 +* Improve detection of completion for Link new device flow by @hughns in https://github.com/element-hq/element-x-android/pull/6681 +* Remove external call support by @bmarty in https://github.com/element-hq/element-x-android/pull/6668 +* [a11y] Fix a set of issues by @bmarty in https://github.com/element-hq/element-x-android/pull/6650 +* Add clipping to RoomSummaryRow by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6654 +* Fix media viewer flickering and crashing by @bxdxnn in https://github.com/element-hq/element-x-android/pull/6715 +* Rename verification methods by @bmarty in https://github.com/element-hq/element-x-android/pull/6726 +* Add a way to tweak MAS url. by @bmarty in https://github.com/element-hq/element-x-android/pull/6682 +* Fix 2 x Crash the app in Developer Options - Update AppDeveloperSettingsView.kt by @escix in https://github.com/element-hq/element-x-android/pull/6708 +* Introduce UI sample by @bmarty in https://github.com/element-hq/element-x-android/pull/6740 + +## New Contributors +* @krbns made their first contribution in https://github.com/element-hq/element-x-android/pull/6622 +* @toger5 made their first contribution in https://github.com/element-hq/element-x-android/pull/6642 +* @manfrommedan made their first contribution in https://github.com/element-hq/element-x-android/pull/6640 +* @Copilot made their first contribution in https://github.com/element-hq/element-x-android/pull/6736 + +**Full Changelog**: https://github.com/element-hq/element-x-android/compare/v26.04.4...v26.05.0 + Changes in Element X v26.04.4 ============================= diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index 70376ffcb9..f2120038a6 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -54,6 +54,7 @@ import io.element.android.features.ftue.api.state.FtueService import io.element.android.features.ftue.api.state.FtueState import io.element.android.features.home.api.HomeEntryPoint import io.element.android.features.linknewdevice.api.LinkNewDeviceEntryPoint +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.networkmonitor.api.NetworkMonitor import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorContainer @@ -151,6 +152,7 @@ class LoggedInFlowNode( private val analyticsService: AnalyticsService, private val analyticsRoomListStateWatcher: AnalyticsRoomListStateWatcher, private val createRoomEntryPoint: CreateRoomEntryPoint, + private val activeLiveLocationShareManager: ActiveLiveLocationShareManager, ) : BaseFlowNode( backstack = BackStack( initialElement = NavTarget.Placeholder, @@ -211,6 +213,7 @@ class LoggedInFlowNode( super.onBuilt() lifecycleScope.launch { sessionEnterpriseService.init() + activeLiveLocationShareManager.setup() } lifecycle.subscribe( onCreate = { @@ -219,7 +222,6 @@ class LoggedInFlowNode( loggedInFlowProcessor.observeEvents(sessionCoroutineScope) matrixClient.sessionVerificationService.setListener(verificationListener) mediaPreviewConfigMigration() - sessionCoroutineScope.launch { // Wait for the network to be connected before pre-fetching the max file upload size networkMonitor.connectivity.first { networkStatus -> networkStatus == NetworkStatus.Connected } diff --git a/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt b/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt index 9b1bbd1b81..1ce423a569 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/di/SyncOrchestrator.kt @@ -89,16 +89,14 @@ class SyncOrchestrator( @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun observeStates() = coroutineScope.launch { Timber.tag(tag).d("start observing the app and network state") - - val isAppActiveFlow = combine( + val isAppActiveFlows = listOf( appForegroundStateService.isInForeground, appForegroundStateService.isInCall, appForegroundStateService.isSyncingNotificationEvent, appForegroundStateService.hasRingingCall, - ) { isInForeground, isInCall, isSyncingNotificationEvent, hasRingingCall -> - isInForeground || isInCall || isSyncingNotificationEvent || hasRingingCall - } - + appForegroundStateService.isSharingLiveLocation + ) + val isAppActiveFlow = combine(isAppActiveFlows) { actives -> actives.any { it } } combine( // small debounce to avoid spamming startSync when the state is changing quickly in case of error. syncService.syncState.debounce(100.milliseconds), diff --git a/enterprise b/enterprise index fb7e9287d9..6781da90aa 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit fb7e9287d9d446012925139842d9aaa8e99a74dc +Subproject commit 6781da90aae61cf77dcdbc543e18d76411d578b4 diff --git a/fastlane/metadata/android/en-US/changelogs/202605010.txt b/fastlane/metadata/android/en-US/changelogs/202605010.txt new file mode 100644 index 0000000000..0ad08f5b4d --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/202605010.txt @@ -0,0 +1,2 @@ +Main changes in this version: improvements in Element Call, room knocking and room directory are now available, improvements on DMs. +Full changelog: https://github.com/element-hq/element-x-android/releases diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt new file mode 100644 index 0000000000..cd47cd8bb1 --- /dev/null +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenBackPressPolicy.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.impl.ui +internal sealed interface CallScreenBackPressAction { + data object DispatchEscapeToWebView : CallScreenBackPressAction + data object EnterPictureInPicture : CallScreenBackPressAction +} + +internal object CallScreenBackPressPolicy { + fun resolve( + supportPip: Boolean, + hasWebView: Boolean, + fromNative: Boolean, + ): CallScreenBackPressAction? { + return when { + hasWebView && fromNative -> CallScreenBackPressAction.DispatchEscapeToWebView + hasWebView && supportPip -> CallScreenBackPressAction.EnterPictureInPicture + else -> null + } + } +} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index 1c68a62f55..2537eb739c 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -17,9 +17,10 @@ import android.webkit.WebChromeClient import android.webkit.WebView import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBars import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -45,7 +46,6 @@ import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.ui.strings.CommonStrings import timber.log.Timber @@ -64,94 +64,93 @@ internal fun CallScreenView( requestPermissions: (Array, RequestPermissionCallback) -> Unit, modifier: Modifier = Modifier, ) { - fun handleBack() { - if (pipState.supportPip) { - pipState.eventSink.invoke(PictureInPictureEvent.EnterPictureInPicture) - } else { - state.eventSink(CallScreenEvent.Hangup) + var callWebView by remember { mutableStateOf(null) } + + fun handleBack(fromNative: Boolean = false) { + when (CallScreenBackPressPolicy.resolve(supportPip = pipState.supportPip, hasWebView = callWebView != null, fromNative)) { + CallScreenBackPressAction.EnterPictureInPicture -> + pipState.eventSink(PictureInPictureEvent.EnterPictureInPicture) + CallScreenBackPressAction.DispatchEscapeToWebView -> + callWebView?.dispatchEscKeyEvent() + null -> Timber.d("Back press with unsupported pip is a no-op") } } - Scaffold( - modifier = modifier, - ) { padding -> - BackHandler { - handleBack() + BackHandler { + handleBack(fromNative = true) + } + if (state.webViewError != null) { + ErrorDialog( + content = buildString { + append(stringResource(CommonStrings.error_unknown)) + state.webViewError.takeIf { it.isNotEmpty() }?.let { append("\n\n").append(it) } + }, + onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, + ) + } else { + var webViewAudioManager by remember { mutableStateOf(null) } + val coroutineScope = rememberCoroutineScope() + + var invalidAudioDeviceReason by remember { mutableStateOf(null) } + invalidAudioDeviceReason?.let { + InvalidAudioDeviceDialog(invalidAudioDeviceReason = it) { + invalidAudioDeviceReason = null + } } - if (state.webViewError != null) { - ErrorDialog( - content = buildString { - append(stringResource(CommonStrings.error_unknown)) - state.webViewError.takeIf { it.isNotEmpty() }?.let { append("\n\n").append(it) } - }, - onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, - ) - } else { - var webViewAudioManager by remember { mutableStateOf(null) } - val coroutineScope = rememberCoroutineScope() - var invalidAudioDeviceReason by remember { mutableStateOf(null) } - invalidAudioDeviceReason?.let { - InvalidAudioDeviceDialog(invalidAudioDeviceReason = it) { - invalidAudioDeviceReason = null - } + CallWebView( + modifier = modifier.consumeWindowInsets(WindowInsets.systemBars).fillMaxSize(), + url = state.urlState, + userAgent = state.userAgent, + onPermissionsRequest = { request -> + val androidPermissions = mapWebkitPermissions(request.resources) + val callback: RequestPermissionCallback = { request.grant(it) } + requestPermissions(androidPermissions.toTypedArray(), callback) + }, + onConsoleMessage = onConsoleMessage, + onCreateWebView = { webView -> + callWebView = webView + webView.addBackHandler(onBackPressed = ::handleBack) + val interceptor = WebViewWidgetMessageInterceptor( + webView = webView, + onUrlLoaded = { url -> + webView.evaluateJavascript("controls.onBackButtonPressed = () => { backHandler.onBackPressed() }", null) + if (webViewAudioManager?.isInCallMode?.get() == false) { + Timber.d("URL $url is loaded, starting in-call audio mode") + webViewAudioManager?.onCallStarted() + } else { + Timber.d("Can't start in-call audio mode since the app is already in it.") + } + }, + onError = { state.eventSink(CallScreenEvent.OnWebViewError(it)) }, + ) + webViewAudioManager = WebViewAudioManager( + webView = webView, + coroutineScope = coroutineScope, + onInvalidAudioDeviceAdded = { invalidAudioDeviceReason = it }, + ) + state.eventSink(CallScreenEvent.SetupMessageChannels(interceptor)) + val pipController = WebViewPipController(webView) + pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) + }, + onDestroyWebView = { + callWebView = null + // Reset audio mode + webViewAudioManager?.onCallStopped() } - - CallWebView( - modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) - .fillMaxSize(), - url = state.urlState, - userAgent = state.userAgent, - onPermissionsRequest = { request -> - val androidPermissions = mapWebkitPermissions(request.resources) - val callback: RequestPermissionCallback = { request.grant(it) } - requestPermissions(androidPermissions.toTypedArray(), callback) - }, - onConsoleMessage = onConsoleMessage, - onCreateWebView = { webView -> - webView.addBackHandler(onBackPressed = ::handleBack) - val interceptor = WebViewWidgetMessageInterceptor( - webView = webView, - onUrlLoaded = { url -> - webView.evaluateJavascript("controls.onBackButtonPressed = () => { backHandler.onBackPressed() }", null) - if (webViewAudioManager?.isInCallMode?.get() == false) { - Timber.d("URL $url is loaded, starting in-call audio mode") - webViewAudioManager?.onCallStarted() - } else { - Timber.d("Can't start in-call audio mode since the app is already in it.") - } - }, - onError = { state.eventSink(CallScreenEvent.OnWebViewError(it)) }, - ) - webViewAudioManager = WebViewAudioManager( - webView = webView, - coroutineScope = coroutineScope, - onInvalidAudioDeviceAdded = { invalidAudioDeviceReason = it }, - ) - state.eventSink(CallScreenEvent.SetupMessageChannels(interceptor)) - val pipController = WebViewPipController(webView) - pipState.eventSink(PictureInPictureEvent.SetPipController(pipController)) - }, - onDestroyWebView = { - // Reset audio mode - webViewAudioManager?.onCallStopped() - } - ) - when (state.urlState) { - AsyncData.Uninitialized, - is AsyncData.Loading -> - ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait)) - is AsyncData.Failure -> { - Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") - ErrorDialog( - content = state.urlState.error.message.orEmpty(), - onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, - ) - } - is AsyncData.Success -> Unit + ) + when (state.urlState) { + AsyncData.Uninitialized, + is AsyncData.Loading -> + ProgressDialog(text = stringResource(id = CommonStrings.common_please_wait)) + is AsyncData.Failure -> { + Timber.e(state.urlState.error, "WebView failed to load URL: ${state.urlState.error.message}") + ErrorDialog( + content = state.urlState.error.message.orEmpty(), + onSubmit = { state.eventSink(CallScreenEvent.Hangup) }, + ) } + is AsyncData.Success -> Unit } } } @@ -248,15 +247,16 @@ private fun WebView.setup( private fun WebView.addBackHandler(onBackPressed: () -> Unit) { addJavascriptInterface( - object { - @Suppress("unused") - @JavascriptInterface - fun onBackPressed() = onBackPressed() - }, + JavascriptBackHandlerBridge(callback = onBackPressed), "backHandler" ) } +private fun WebView.dispatchEscKeyEvent() { + dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_ESCAPE)) + dispatchKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_ESCAPE)) +} + @PreviewsDayNight @Composable internal fun CallScreenViewPreview( @@ -275,3 +275,12 @@ internal fun CallScreenViewPreview( internal fun InvalidAudioDeviceDialogPreview() = ElementPreview { InvalidAudioDeviceDialog(invalidAudioDeviceReason = InvalidAudioDeviceReason.BT_AUDIO_DEVICE_DISABLED) {} } + +internal class JavascriptBackHandlerBridge( + private val callback: () -> Unit, +) { + @JavascriptInterface + fun onBackPressed() { + callback() + } +} diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index 367328ed10..26df7c160c 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -32,6 +32,9 @@ import androidx.compose.runtime.rememberUpdatedState import androidx.core.app.PictureInPictureModeChangedInfo import androidx.core.content.IntentCompat import androidx.core.util.Consumer +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.lifecycle.Lifecycle import dev.zacsweers.metro.Inject import io.element.android.compound.colors.SemanticColorsLightDark @@ -52,6 +55,7 @@ import io.element.android.libraries.audio.api.AudioFocusRequester import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.designsystem.theme.ElementThemeApp +import io.element.android.libraries.designsystem.utils.hasCompactHeightWindowSize import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.preferences.api.store.AppPreferencesStore import timber.log.Timber @@ -111,6 +115,27 @@ class ElementCallActivity : val colors by remember(webViewTarget.value?.sessionId) { enterpriseService.semanticColorsFlow(sessionId = webViewTarget.value?.sessionId) }.collectAsState(SemanticColorsLightDark.default) + + // When the height is compact, hide the system bars by default to maximize the space for the call, using immersive mode + val hasCompactHeight = hasCompactHeightWindowSize() + DisposableEffect(hasCompactHeight, pipState.isInPictureInPicture) { + if (hasCompactHeight && !pipState.isInPictureInPicture) { + val window = this@ElementCallActivity.window ?: return@DisposableEffect onDispose {} + val insetsController = WindowCompat.getInsetsController(window, window.decorView) + val systemBarInsets = WindowInsetsCompat.Type.systemBars() + insetsController.hide(systemBarInsets) + + insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + + onDispose { + insetsController.show(systemBarInsets) + insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_DEFAULT + } + } else { + onDispose {} + } + } + ElementThemeApp( appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt index b31b6152d0..8de7b81d6d 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt @@ -14,7 +14,6 @@ import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.matrix.api.MatrixClientProvider import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.SessionId -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.services.appnavstate.api.ActiveRoomsHolder diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt new file mode 100644 index 0000000000..f07f7039d3 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenBackPressPolicyTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.ui + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.impl.ui.CallScreenBackPressAction +import io.element.android.features.call.impl.ui.CallScreenBackPressPolicy +import org.junit.Test + +class CallScreenBackPressPolicyTest { + @Test + fun `resolve returns dispatch escape when a web view is available and native button is pressed`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = true, + fromNative = true, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) + } + + @Test + fun `resolve dispatch escape when there is a web view and pip is supported on native button press`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = true, + fromNative = true, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.DispatchEscapeToWebView) + } + + @Test + fun `resolve returns hangup when there is no web view and pip is not supported from native button`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = false, + fromNative = true, + ) + + assertThat(result).isNull() + } + + @Test + fun `resolve returns hangup when there is no web view even though pip is supported from native button`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = false, + fromNative = true, + ) + + assertThat(result).isNull() + } + + @Test + fun `resolve goes to pip if its not from native but from the webview`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = true, + fromNative = false, + ) + + assertThat(result).isEqualTo(CallScreenBackPressAction.EnterPictureInPicture) + } + @Test + fun `resolve hangs up if its not from native but from the webview and pip is not supported`() { + val result = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = true, + fromNative = false, + ) + + assertThat(result).isNull() + } + + @Test + fun `invalid cases (event comes from webview but there is now webview) all result in hangup`() { + val withPipSupport = CallScreenBackPressPolicy.resolve( + supportPip = true, + hasWebView = false, + fromNative = false, + ) + assertThat(withPipSupport).isNull() + val withOutPipSupport = CallScreenBackPressPolicy.resolve( + supportPip = false, + hasWebView = false, + fromNative = false, + ) + assertThat(withOutPipSupport).isNull() + } +} diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt new file mode 100644 index 0000000000..99aaee6f39 --- /dev/null +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/ui/CallScreenViewTest.kt @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.call.ui + +import android.view.KeyEvent +import android.webkit.WebView +import androidx.activity.ComponentActivity +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.test.AndroidComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.v2.runAndroidComposeUiTest +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.call.impl.pip.PictureInPictureEvent +import io.element.android.features.call.impl.pip.PictureInPictureState +import io.element.android.features.call.impl.pip.aPictureInPictureState +import io.element.android.features.call.impl.ui.CallScreenEvent +import io.element.android.features.call.impl.ui.CallScreenState +import io.element.android.features.call.impl.ui.CallScreenView +import io.element.android.features.call.impl.ui.JavascriptBackHandlerBridge +import io.element.android.features.call.impl.ui.aCallScreenState +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.pressBackKey +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements +import org.robolectric.annotation.Resetter +import org.robolectric.shadows.ShadowWebView + +@OptIn(ExperimentalTestApi::class) +@RunWith(AndroidJUnit4::class) +class CallScreenViewTest { + @Test + fun `pressing back key triggers hangup when no web view is available and pip is unsupported`() = runAndroidComposeUiTest { + val callEvents = EventsRecorder() + + setCallScreenView( + state = aCallScreenState(eventSink = callEvents), + useInspectionMode = true, + ) + + pressBackKey() + + callEvents.assertEmpty() + } + + @Config(shadows = [RecordingShadowWebView::class]) + @Test + fun `pressing back key dispatches escape key events to web view when pip is unsupported`() = runAndroidComposeUiTest { + setCallScreenView( + state = aCallScreenState(), + useInspectionMode = false, + pipState = aPictureInPictureState(supportPip = false), + ) + + pressBackKey() + + val dispatchedEvents = RecordingShadowWebView.dispatchedEvents + assertEquals(2, dispatchedEvents.size) + assertEquals(KeyEvent.ACTION_DOWN, dispatchedEvents[0].action) + assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[0].keyCode) + assertEquals(KeyEvent.ACTION_UP, dispatchedEvents[1].action) + assertEquals(KeyEvent.KEYCODE_ESCAPE, dispatchedEvents[1].keyCode) + } + + @Config(shadows = [RecordingShadowWebView::class]) + @Test + fun `web view javascript back handler emits pip event when pip is supported`() = runAndroidComposeUiTest { + val pipEvents = EventsRecorder() + + setCallScreenView( + state = aCallScreenState(), + useInspectionMode = false, + pipState = aPictureInPictureState( + supportPip = true, + eventSink = pipEvents, + ), + ) + + runOnIdle { + RecordingShadowWebView.invokeJavascriptBackHandler() + } + + pipEvents.assertSize(2) + pipEvents.assertTrue(0) { it is PictureInPictureEvent.SetPipController } + pipEvents.assertTrue(1) { it is PictureInPictureEvent.EnterPictureInPicture } + } +} + +@OptIn(ExperimentalTestApi::class) +private fun AndroidComposeUiTest.setCallScreenView( + state: CallScreenState, + useInspectionMode: Boolean, + pipState: PictureInPictureState = aPictureInPictureState(supportPip = false), +) { + setContent { + // Inspection mode disables AndroidView creation; keep it configurable per test. + CompositionLocalProvider(LocalInspectionMode provides useInspectionMode) { + CallScreenView( + state = state, + pipState = pipState, + onConsoleMessage = {}, + requestPermissions = { _, _ -> }, + ) + } + } +} + +@Implements(WebView::class) +internal class RecordingShadowWebView : ShadowWebView() { + companion object { + val dispatchedEvents = mutableListOf() + private var backHandlerJavascriptInterface: JavascriptBackHandlerBridge? = null + + @Resetter + @JvmStatic + @Suppress("unused") + fun resetRecordedEvents() { + dispatchedEvents.clear() + backHandlerJavascriptInterface = null + } + + fun invokeJavascriptBackHandler() { + val backHandler = checkNotNull(backHandlerJavascriptInterface) { "Expected backHandler JavaScript interface to be registered" } + backHandler.onBackPressed() + } + } + + @Implementation + protected override fun addJavascriptInterface(`object`: Any, name: String) { + super.addJavascriptInterface(`object`, name) + if (name == "backHandler") { + backHandlerJavascriptInterface = `object` as? JavascriptBackHandlerBridge + } + } + + @Implementation + @Suppress("unused") + fun dispatchKeyEvent(event: KeyEvent): Boolean { + dispatchedEvents += KeyEvent(event) + return false + } +} diff --git a/features/createroom/impl/src/main/res/values-pl/translations.xml b/features/createroom/impl/src/main/res/values-pl/translations.xml index 0164225ea2..b602cb13d8 100644 --- a/features/createroom/impl/src/main/res/values-pl/translations.xml +++ b/features/createroom/impl/src/main/res/values-pl/translations.xml @@ -3,14 +3,34 @@ "Nowy pokój" "Zaproś znajomych" "Wystąpił błąd w trakcie tworzenia pokoju" - "Tylko zaproszone osoby mogą dołączyć do tego pokoju. Wszystkie wiadomości są szyfrowane end-to-end." + "Nie udało się utworzyć przestrzeni z powodu nieznanego błędu. Spróbuj ponownie później." + "Dodaj nazwę…" + "Nowy pokój" + "Nowa przestrzeń" + "Dołączyć mogą tylko zaproszone osoby." + "Prywatny" "Każdy może znaleźć ten pokój. Możesz to zmienić w ustawieniach pokoju." - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę" - "Poproś o dołączenie" - "Każdy może dołączyć do tego pokoju" - "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju." - "Adres pokoju" + "Każdy może dołączyć." + "Publiczny" + "Każdy może poprosić o dołączenie, ale administrator lub moderator musi to zaakceptować." + "Zezwól na prośbę o dołączenie" + "Każdy w %1$s może dołączyć, ale wszyscy pozostali muszą poprosić o dostęp." + "Poproś o dołączenie" + "Dołączyć mogą tylko zaproszone osoby." + "Prywatny" + "Każdy może dołączyć." + "Publiczny" + "Każdy w %1$s może dołączyć." + "Standardowy" + "Kto ma dostęp" + "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, potrzebny jest adres pokoju." + "Adres" "Widoczność pomieszczenia" + "(brak przestrzeni)" + "Nie dodawaj do przestrzeni" + "Nie wybrano przestrzeni" + "Dodaj do przestrzeni" "Temat (opcjonalnie)" + "Dodaj opis…" diff --git a/features/createroom/impl/src/main/res/values-uk/translations.xml b/features/createroom/impl/src/main/res/values-uk/translations.xml index d01da0dc35..a40a2b21a5 100644 --- a/features/createroom/impl/src/main/res/values-uk/translations.xml +++ b/features/createroom/impl/src/main/res/values-uk/translations.xml @@ -3,22 +3,32 @@ "Нова кімната" "Запросити людей" "Під час створення кімнати сталася помилка" + "Простір не вдалося створити через невідому помилку. Спробуйте ще раз пізніше." "Додати назву…" "Нова кімната" "Новий простір" "Можуть приєднатися лише запрошені люди." + "Приватний" "Будь-хто може знайти цю кімнату. Ви можете змінити це в будь-який час у налаштуваннях кімнати." "Приєднатися може будь-хто." + "Публічний" "Будь-хто може подати запит на приєднання, але адміністратор або модератор повинен схвалити запит." "Дозволити запит на приєднання" + "Будь-хто з %1$s може приєднатися, але всі інші повинні подати запит на доступ." + "Запит на приєднання" "Приєднатися можуть лише запрошені особи." + "Приватний" "Приєднатися може будь-хто." + "Публічний" "Приєднатися може будь-хто з %1$s." + "Стандартний" "Хто має доступ" "Вам знадобиться адреса, щоб зробити її видимою в загальнодоступному каталозі." "Адреса" "Видимість кімнати" + "(без пробілу)" + "Не додавати до простору" "Головна" "Додати до простору" "Тема (необов\'язково)" diff --git a/features/deactivation/impl/src/main/res/values-el/translations.xml b/features/deactivation/impl/src/main/res/values-el/translations.xml index ac645f3063..b6a359abbf 100644 --- a/features/deactivation/impl/src/main/res/values-el/translations.xml +++ b/features/deactivation/impl/src/main/res/values-el/translations.xml @@ -1,14 +1,14 @@ - "Παρακαλώ επιβεβαίωσε ότι θες να απενεργοποιήσεις τον λογαριασμό σου. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί." + "Επιβεβαιώστε ότι θέλετε να διαγράψετε τον λογαριασμό σας. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί." "Διαγραφή όλων των μηνυμάτων μου" "Προειδοποίηση: Οι μελλοντικοί χρήστες ενδέχεται να βλέπουν ελλιπείς συνομιλίες." - "Η απενεργοποίηση του λογαριασμού σας είναι %1$s, θα:" + "Η διαγραφή του λογαριασμού σας είναι %1$s, και θα:" "μη αναστρέψιμο" "%1$s τον λογαριασμό σου (δεν μπορείς να συνδεθείς ξανά και το αναγνωριστικό σου δεν μπορεί να επαναχρησιμοποιηθεί)." "Μόνιμη απενεργοποίηση" "Αποχώρησή σας από όλες τις αίθουσες συνομιλίας." "Διαγράψει τα στοιχεία του λογαριασμού σου από τον διακομιστή ταυτότητάς μας." "Τα μηνύματά σου θα εξακολουθούν να είναι ορατά στους εγγεγραμμένους χρήστες, αλλά δεν θα είναι διαθέσιμα σε νέους ή μη εγγεγραμμένους χρήστες εάν επιλέξεις να τα διαγράψεις." - "Απενεργοποίηση λογαριασμού" + "Διαγραφή λογαριασμού" diff --git a/features/deactivation/impl/src/main/res/values-et/translations.xml b/features/deactivation/impl/src/main/res/values-et/translations.xml index 95695fef16..1776e2de17 100644 --- a/features/deactivation/impl/src/main/res/values-et/translations.xml +++ b/features/deactivation/impl/src/main/res/values-et/translations.xml @@ -1,6 +1,6 @@ - "Palun kinnita uuesti, et soovid eemaldada oma konto kasutusest" + "Palun kinnita uuesti, et soovid kustutada oma kasutajakonto. Seda tegevust ei saa tagasi pöörata." "Kustuta kõik minu sõnumid" "Hoiatus: tulevased kasutajad võivad näha poolikuid vestlusi." "Sinu konto kasutusest eemaldamine on %1$s ja sellega:" @@ -10,5 +10,5 @@ "Sind logitakse välja kõikidest jututubadest." "Kustutatakse sinu andmed meie isikutuvastusserverist." "Sinu sõnumid on jätkuvalt nähtavad registreeritud kasutajatele, kuid kui otsustad sõnumid kustutada, siis nad nad pole nähtavad uutele ja registreerimata kasutajatele." - "Eemalda konto kasutusest" + "Kustuta kasutajakonto" diff --git a/features/deactivation/impl/src/main/res/values-it/translations.xml b/features/deactivation/impl/src/main/res/values-it/translations.xml index 7cd484d0e4..e3de1ec8bb 100644 --- a/features/deactivation/impl/src/main/res/values-it/translations.xml +++ b/features/deactivation/impl/src/main/res/values-it/translations.xml @@ -1,14 +1,14 @@ - "Conferma di voler disattivare il tuo account. Questa azione è irreversibile." + "Conferma di voler eliminare il tuo account. Questa azione è irreversibile." "Elimina tutti i miei messaggi" "Attenzione: gli utenti futuri potrebbero vedere conversazioni incomplete." - "La disattivazione del tuo account è %1$s , quindi:" + "L\'eliminazione del tuo account è %1$s, e comporterà:" "irreversibile" "%1$s il tuo account (non puoi riaccedere e il tuo ID non può essere riutilizzato)." "Disattiva permanentemente" "Ti rimuove da tutte le stanze di chat." "Elimina le informazioni del tuo account dal nostro server di identità." "I tuoi messaggi saranno ancora visibili agli utenti registrati, ma non saranno disponibili per gli utenti nuovi o non registrati se decidi di eliminarli." - "Disattivazione dell\'account" + "Elimina account" diff --git a/features/deactivation/impl/src/main/res/values-pl/translations.xml b/features/deactivation/impl/src/main/res/values-pl/translations.xml index bddb6a9037..5778123aa5 100644 --- a/features/deactivation/impl/src/main/res/values-pl/translations.xml +++ b/features/deactivation/impl/src/main/res/values-pl/translations.xml @@ -1,14 +1,14 @@ - "Potwierdź dezaktywacje konta. Tej akcji nie można cofnąć." + "Potwierdź usunięcie konta. Tej akcji nie można cofnąć." "Usuń wszystkie moje wiadomości" "Ostrzeżenie: Przyszli użytkownicy mogą zobaczyć niekompletne rozmowy." - "Dezaktywacja konta jest %1$s, zostanie:" + "Usunięcie konta jest %1$s, co spowoduje:" "nieodwracalna" "%1$s twoje konto (nie będziesz mógł się zalogować, a twoje ID przepadnie)." "Permanentnie wyłączy" "Usunie Ciebie ze wszystkich pokoi rozmów." "Usunięte wszystkie dane konta z naszego serwera tożsamości." "Twoje wiadomości wciąż będą widoczne dla zarejestrowanych użytkowników, ale nie będą dostępne dla nowych lub niezarejestrowanych użytkowników, jeśli je usuniesz." - "Dezaktywuj konto" + "Usuń konto" diff --git a/features/deactivation/impl/src/main/res/values-uz/translations.xml b/features/deactivation/impl/src/main/res/values-uz/translations.xml index d357f38186..e0dcfe59ef 100644 --- a/features/deactivation/impl/src/main/res/values-uz/translations.xml +++ b/features/deactivation/impl/src/main/res/values-uz/translations.xml @@ -10,4 +10,5 @@ "Sizni barcha chat xonalaridan olib tashlash." "Hisobingiz haqidagi axborotni identifikatsiya serverimizdan o‘chirib tashlang." "Xabarlaringiz ro‘yxatdan o‘tgan foydalanuvchilarga ko‘rinadi, lekin ularni o‘chirishni tanlasangiz, yangi yoki ro‘yxatdan o‘tmagan foydalanuvchilarga ko‘rinmaydi." + "Akkauntni o‘chirish" diff --git a/features/ftue/impl/src/main/res/values-pl/translations.xml b/features/ftue/impl/src/main/res/values-pl/translations.xml index 5d77c57994..45ca82ede6 100644 --- a/features/ftue/impl/src/main/res/values-pl/translations.xml +++ b/features/ftue/impl/src/main/res/values-pl/translations.xml @@ -2,8 +2,8 @@ "Nie możesz potwierdzić?" "Utwórz nowy klucz przywracania" - "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." - "Potwierdź, że to Ty" + "Wybierz sposób weryfikacji, aby skonfigurować bezpieczne wiadomości." + "Potwierdź swoją tożsamość cyfrową" "Użyj innego urządzenia" "Użyj klucza przywracania" "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt index 26054d7e56..e34f2845da 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt @@ -19,7 +19,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter import io.element.android.libraries.matrix.api.room.CallIntentConsensus import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.roomlist.LatestEventValue import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.ui.model.getAvatarData diff --git a/features/home/impl/src/main/res/values-et/translations.xml b/features/home/impl/src/main/res/values-et/translations.xml index c1f61bfa29..9d938ed941 100644 --- a/features/home/impl/src/main/res/values-et/translations.xml +++ b/features/home/impl/src/main/res/values-et/translations.xml @@ -7,7 +7,7 @@ "Oleme sinu helisid värskendanud" "Loo uus taastevõti, mida saad kasutada oma krüptitud sõnumite ajaloo taastamisel olukorras, kus kaotad ligipääsu oma seadmetele." "Seadista andmete taastamine" - "Seadista taastamine" + "Varunda oma vestlused" "Säilitamaks ligipääsu vestluste ja krüptovõtmete varukoopiale, palun sisesta kinnituseks oma taastevõti." "Sisesta oma taastevõti" "Kas unustasid oma taastevõtme?" diff --git a/features/home/impl/src/main/res/values-fa/translations.xml b/features/home/impl/src/main/res/values-fa/translations.xml index aec50309d8..b0c6a30bc4 100644 --- a/features/home/impl/src/main/res/values-fa/translations.xml +++ b/features/home/impl/src/main/res/values-fa/translations.xml @@ -4,7 +4,7 @@ "از کار انداختن بهینه سازی" "آگاهی‌ها نمی‌رسند؟" "بازگردانی تاریخچهٔ پیام‌ها و هویت رمزنگاشته‌تان با کلید بازیابی در صورت از دست دادن همهٔ افزاره‌های موجودتان." - "برپایی بازیابی" + "دریافت کلید بازیابی" "برپایی بازیابی" "کلید بازیابی خود را تأیید کنید تا دسترسی به حافظه کلیدها و تاریخچه پیام‌هایتان حفظ شود ." "ورود کلید بازیابیتان" @@ -25,6 +25,7 @@ "آغاز با پیام دادن به کسی." "هنوز گپی وجود ندارد." "علاقه‌مندی‌ها" + "می‌توانید در تنظیمات چت، یک چت را به موارد دلخواه خود اضافه کنید. فعلاً می‌توانید فیلترها را غیرفعال کنید تا چت‌های دیگر خود را ببینید." "هنوز هیچ گپ مورد علاقه‌ای ندارید" "دعوت‌ها" "هیچ دعوت منتظری ندارید." diff --git a/features/home/impl/src/main/res/values-pl/translations.xml b/features/home/impl/src/main/res/values-pl/translations.xml index 73e0b5e52e..0c1b07f27b 100644 --- a/features/home/impl/src/main/res/values-pl/translations.xml +++ b/features/home/impl/src/main/res/values-pl/translations.xml @@ -5,9 +5,9 @@ "Powiadomienia nie dochodzą?" "Sygnał powiadomień został zaktualizowany — jest wyraźniejszy, szybszy i mniej uciążliwy." "Odświeżyliśmy Twoje dźwięki" - "Wygeneruj nowy klucz przywracania, którego można użyć do przywrócenia historii wiadomości szyfrowanych w przypadku utraty dostępu do swoich urządzeń." - "Skonfiguruj przywracanie" - "Skonfiguruj przywracanie" + "Twoje czaty są automatycznie archiwizowane za pomocą szyfrowania end-to-end. Aby przywrócić tę kopię zapasową i swoją tożsamość cyfrową, wymagany będzie klucz przywracania." + "Uzyskaj klucz przywracania" + "Utwórz kopię zapasową swoich czatów" "Potwierdź klucz przywracania, aby zachować dostęp do magazynu kluczy i historii wiadomości." "Wprowadź klucz przywracania" "Zapomniałeś klucza przywracania?" @@ -50,6 +50,7 @@ Nie masz żadnych nieprzeczytanych wiadomości!" "Oznacz jako przeczytane" "Oznacz jako nieprzeczytane" "Ten pokój został ulepszony" + "Twoje przestrzenie" "Wygląda na to, że używasz nowego urządzenia. Zweryfikuj się innym urządzeniem, aby uzyskać dostęp do zaszyfrowanych wiadomości." "Potwierdź, że to Ty" diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt index 696e02a0d7..8bfea2c12c 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/InviteData.kt @@ -11,7 +11,6 @@ package io.element.android.features.invite.api import android.os.Parcelable import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo import io.element.android.libraries.matrix.api.spaces.SpaceRoom import kotlinx.parcelize.Parcelize diff --git a/features/invitepeople/impl/src/main/res/values-it/translations.xml b/features/invitepeople/impl/src/main/res/values-it/translations.xml index 979e42de1b..82dc6126f1 100644 --- a/features/invitepeople/impl/src/main/res/values-it/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-it/translations.xml @@ -2,4 +2,8 @@ "Già membro" "Già invitato" + "Al momento non hai conversazioni con questi contatti. Conferma di invitarli in questa stanza prima di continuare." + "Al momento non hai converszioni con questo contatto. Conferma di invitarlo in questa stanza prima di continuare." + "Invita nuovi contatti in questa stanza?" + "Invitare un nuovo contatto in questa stanza?" diff --git a/features/invitepeople/impl/src/main/res/values-pl/translations.xml b/features/invitepeople/impl/src/main/res/values-pl/translations.xml index bfd537bb4b..3e8371c1ab 100644 --- a/features/invitepeople/impl/src/main/res/values-pl/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-pl/translations.xml @@ -2,4 +2,8 @@ "Jest już członkiem" "Już zaproszony" + "Obecnie nie prowadzisz żadnych czatów z tymi kontaktami. Potwierdź zaproszenie, zanim przejdziesz dalej." + "Obecnie nie posiadasz żadnych czatów z tym kontaktem. Potwierdź zaproszenie, zanim przejdziesz dalej." + "Zaprosić nowe kontakty do tego pokoju?" + "Zaprosić nowy kontakt do tego pokoju?" diff --git a/features/invitepeople/impl/src/main/res/values-uk/translations.xml b/features/invitepeople/impl/src/main/res/values-uk/translations.xml index da3ac9fe5b..b7bb3c95d9 100644 --- a/features/invitepeople/impl/src/main/res/values-uk/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-uk/translations.xml @@ -2,4 +2,8 @@ "Уже учасник" "Уже запрошені" + "Наразі у вас немає чатів із цими контактами. Підтвердьте запрошення їх до цієї кімнати, перш ніж продовжувати." + "Наразі у вас немає чатів із цим контактом. Підтвердьте запрошення до цієї кімнати, перш ніж продовжувати." + "Запросити нових контактів до цієї кімнати?" + "Запросити нового контакта до цієї кімнати?" diff --git a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt index 4ecd74a42f..5d5a533bb6 100644 --- a/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt +++ b/features/invitepeople/impl/src/test/kotlin/io/element/android/features/invitepeople/impl/DefaultInvitePeoplePresenterTest.kt @@ -540,7 +540,7 @@ internal class DefaultInvitePeoplePresenterTest { } @Test - fun `present - suggestions are loaded from recent direct rooms`() = runTest { + fun `present - suggestions are loaded from recent DM rooms`() = runTest { val dmRoomId = RoomId("!dm_room:server.org") val otherUserId = UserId("@frank:server.org") val matrixClient = FakeMatrixClient(sessionId = A_USER_ID).apply { @@ -554,7 +554,7 @@ internal class DefaultInvitePeoplePresenterTest { roomId = dmRoomId, initialRoomInfo = aRoomInfo( id = dmRoomId, - isDirect = true, + isDm = true, activeMembersCount = 2, currentUserMembership = CurrentUserMembership.JOINED, ), @@ -591,7 +591,7 @@ internal class DefaultInvitePeoplePresenterTest { roomId = dmRoomId, initialRoomInfo = aRoomInfo( id = dmRoomId, - isDirect = true, + isDm = true, activeMembersCount = 2, currentUserMembership = CurrentUserMembership.JOINED, ), diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 1e685d3f5a..d257952209 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -44,7 +44,6 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipDetails import io.element.android.libraries.matrix.api.room.RoomType -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo diff --git a/features/joinroom/impl/src/main/res/values-uk/translations.xml b/features/joinroom/impl/src/main/res/values-uk/translations.xml index ec2a24950a..1a83a6ca8c 100644 --- a/features/joinroom/impl/src/main/res/values-uk/translations.xml +++ b/features/joinroom/impl/src/main/res/values-uk/translations.xml @@ -15,6 +15,7 @@ "Вам потрібно отримати запрошення, щоб приєднатися, інакше доступ може бути обмежений." "Забути" "Вам потрібне запрошення, щоб приєднатися" + "Запрошено користувачем" "Доєднатися" "Можливо, вам знадобиться отримати запрошення або стати учасником простору, щоб приєднатися." "Постукати, щоб приєднатися" diff --git a/features/knockrequests/impl/build.gradle.kts b/features/knockrequests/impl/build.gradle.kts index 6f030479f5..e6a1a30167 100644 --- a/features/knockrequests/impl/build.gradle.kts +++ b/features/knockrequests/impl/build.gradle.kts @@ -33,9 +33,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.uiStrings) implementation(projects.libraries.designsystem) - implementation(projects.libraries.featureflag.api) testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.libraries.featureflag.test) } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt index b51b78f105..73e4a2ddeb 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsModule.kt @@ -15,8 +15,6 @@ import dev.zacsweers.metro.SingleIn import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.features.knockrequests.api.knockRequestPermissions import io.element.android.libraries.di.RoomScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.powerlevels.permissionsFlow @@ -25,14 +23,13 @@ import io.element.android.libraries.matrix.api.room.powerlevels.permissionsFlow object KnockRequestsModule { @Provides @SingleIn(RoomScope::class) - fun knockRequestsService(room: JoinedRoom, featureFlagService: FeatureFlagService): KnockRequestsService { + fun knockRequestsService(room: JoinedRoom): KnockRequestsService { return KnockRequestsService( knockRequestsFlow = room.knockRequestsFlow, permissionsFlow = room.permissionsFlow(KnockRequestPermissions.DEFAULT) { perms -> perms.knockRequestPermissions() }, - isKnockFeatureEnabledFlow = featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock), - coroutineScope = room.roomCoroutineScope + coroutineScope = room.roomCoroutineScope, ) } } diff --git a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt index 98570e6b28..00e0a30563 100644 --- a/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt +++ b/features/knockrequests/impl/src/main/kotlin/io/element/android/features/knockrequests/impl/data/KnockRequestsService.kt @@ -12,7 +12,6 @@ import io.element.android.features.knockrequests.api.KnockRequestPermissions import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.knock.KnockRequest -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async @@ -28,26 +27,20 @@ import kotlinx.coroutines.supervisorScope class KnockRequestsService( knockRequestsFlow: Flow>, permissionsFlow: Flow, - isKnockFeatureEnabledFlow: Flow, coroutineScope: CoroutineScope, ) { // Keep track of the knock requests that have been handled, so we don't have to wait for sync to remove them. private val handledKnockRequestIds = MutableStateFlow>(emptySet()) val knockRequestsFlow = combine( - isKnockFeatureEnabledFlow, knockRequestsFlow, handledKnockRequestIds, - ) { isKnockEnabled, knockRequests, handledKnockIds -> - if (!isKnockEnabled) { - AsyncData.Success(persistentListOf()) - } else { - val presentableKnockRequests = knockRequests - .filter { it.eventId !in handledKnockIds } - .map { inner -> KnockRequestWrapper(inner) } - .toImmutableList() - AsyncData.Success(presentableKnockRequests) - } + ) { knockRequests, handledKnockIds -> + val presentableKnockRequests = knockRequests + .filter { it.eventId !in handledKnockIds } + .map { inner -> KnockRequestWrapper(inner) } + .toImmutableList() + AsyncData.Success(presentableKnockRequests) }.stateIn(coroutineScope, SharingStarted.Lazily, AsyncData.Loading()) val permissionsFlow = permissionsFlow.stateIn( diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt index 3161d3e81f..1595fcdbd9 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/banner/KnockRequestsBannerPresenterTest.kt @@ -28,18 +28,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class KnockRequestsBannerPresenterTest { - @Test - fun `present - when feature is disabled then the banner should be hidden`() = runTest { - val knockRequests = flowOf(listOf(FakeKnockRequest())) - val presenter = createKnockRequestsBannerPresenter(isFeatureEnabled = false, knockRequestsFlow = knockRequests) - presenter.test { - skipItems(1) - awaitItem().also { state -> - assertThat(state.isVisible).isFalse() - } - } - } - @Test fun `present - when empty knock request list then the banner should be hidden`() = runTest { val knockRequests = flowOf(emptyList()) @@ -229,12 +217,10 @@ import org.junit.Test private fun TestScope.createKnockRequestsBannerPresenter( knockRequestsFlow: Flow> = flowOf(emptyList()), canAcceptKnockRequests: Boolean = true, - isFeatureEnabled: Boolean = true, ): KnockRequestsBannerPresenter { val knockRequestsService = KnockRequestsService( knockRequestsFlow = knockRequestsFlow, coroutineScope = backgroundScope, - isKnockFeatureEnabledFlow = flowOf(isFeatureEnabled), permissionsFlow = flowOf(KnockRequestPermissions(canAcceptKnockRequests, canAcceptKnockRequests, canAcceptKnockRequests)), ) return KnockRequestsBannerPresenter( diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt index 7102b01773..209e67cadf 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt @@ -298,7 +298,6 @@ internal fun TestScope.createKnockRequestsListPresenter( val knockRequestsService = KnockRequestsService( knockRequestsFlow = knockRequestsFlow, coroutineScope = backgroundScope, - isKnockFeatureEnabledFlow = flowOf(true), permissionsFlow = flowOf(KnockRequestPermissions(canAccept, canDecline, canBan)), ) return KnockRequestsListPresenter(knockRequestsService = knockRequestsService) diff --git a/features/leaveroom/api/src/main/res/values-fa/translations.xml b/features/leaveroom/api/src/main/res/values-fa/translations.xml index 167070891f..ec2cd89314 100644 --- a/features/leaveroom/api/src/main/res/values-fa/translations.xml +++ b/features/leaveroom/api/src/main/res/values-fa/translations.xml @@ -1,5 +1,6 @@ + "آیا مطمئنید که می‌خواهید این مکالمه را ترک کنید؟ این مکالمه عمومی نیست و بدون دعوت نمی‌توانید دوباره به آن بپیوندید." "مطمئنید که می‌خواهید این اتاق را ترک کنید؟ تنها فرد این‌جا هستید. در صورت ترک، هیچ‌کسی از جمله خودتان در آینده نخواهد توانست به آن بپیوندد." "مطمئنید که می‌خواهید این اتاق را ترک کنید؟ این اتاق عمومی نبوده قادر نخواهید بود بدون دعوت دوباره بپیوندید." "گزینش مالکان" diff --git a/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt b/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt index 6455b45659..d11dc7e7e8 100644 --- a/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt +++ b/features/leaveroom/impl/src/main/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenter.kt @@ -24,7 +24,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.usersWithRole import io.element.android.libraries.push.api.notifications.conversations.NotificationConversationService import kotlinx.coroutines.CoroutineScope diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt index 59d2c1ce23..90b7f2369f 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveBaseRoomPresenterTest.kt @@ -115,7 +115,7 @@ class LeaveBaseRoomPresenterTest { givenGetRoomResult( roomId = A_ROOM_ID, result = FakeBaseRoom().apply { - givenRoomInfo(aRoomInfo(isDirect = true, activeMembersCount = 2)) + givenRoomInfo(aRoomInfo(isDm = true, activeMembersCount = 2)) }, ) } diff --git a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml index 18b731a528..ced8955d1d 100644 --- a/features/linknewdevice/impl/src/main/res/values-pl/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-pl/translations.xml @@ -1,16 +1,33 @@ "Skanuj kod QR" + "Otwórz %1$s na laptopie lub komputerze stacjonarnym" "Zeskanuj kod QR za pomocą tego urządzenia" "Gotowy do skanowania" + "Otwórz %1$s na komputerze stacjonarnym, aby uzyskać kod QR" + "Liczby nie pasują do siebie" + "Wprowadź 2-cyfrowy kod" + "Pozwoli to sprawdzić, czy połączenie z drugim urządzeniem jest bezpieczne." + "Wprowadź numer wyświetlany na drugim urządzeniu" "Twój dostawca konta nie obsługuje %1$s." "%1$s nie jest wspierany" + "Twój dostawca konta nie wspiera logowania na nowym urządzeniu za pomocą kodu QR." "Kod QR nie jest wspierany" "Logowanie zostało anulowane na drugim urządzeniu." "Prośba o logowanie została anulowana" "Logowanie wygasło. Spróbuj ponownie." "Logowanie nie zostało ukończone na czas" + "Otwórz %1$s na drugim urządzeniu" "Wybierz %1$s" + "“Zaloguj się za pomocą kodu QR”" + "Zeskanuj kod QR pokazany tutaj za pomocą drugiego urządzenia" + "Otwórz %1$s na drugim urządzeniu" + "Komputer stacjonarny" + "Ładowanie kodu QR…" + "Urządzenie mobilne" + "Jakiego typu urządzenie chcesz powiązać?" + "Spróbuj ponownie i upewnij się, że 2-cyfrowy kod został wpisany prawidłowo. Jeśli liczby wciąż się nie zgadzają, skontaktuj się ze swoim dostawcą konta." + "Liczby nie pasują do siebie" "Nie udało się nawiązać bezpiecznego połączenia z nowym urządzeniem. Twoje istniejące urządzenia są nadal bezpieczne i nie musisz się o nie martwić." "Co teraz?" "Spróbuj zalogować się ponownie za pomocą kodu QR, jeśli byłby to problem z siecią" @@ -23,6 +40,8 @@ "Prośba o logowanie została anulowana" "Logowanie zostało odrzucone na drugim urządzeniu." "Logowanie odrzucone" + "Nie musisz już robić nic więcej." + "Twoje drugie urządzenie jest już zalogowane" "Logowanie wygasło. Spróbuj ponownie." "Logowanie nie zostało ukończone na czas" "Twoje drugie urządzenie nie wspiera logowania się do %s za pomocą kodu QR. diff --git a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml index fe5b1a7460..752b5ead3f 100644 --- a/features/linknewdevice/impl/src/main/res/values-uk/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-uk/translations.xml @@ -26,6 +26,7 @@ "Завантаження QR-коду…" "Мобільний пристрій" "Який тип пристрою ви хочете під\'єднати?" + "Спробуйте ще раз і переконайтеся, що ви правильно ввели двозначний код. Якщо цифри все одно не збігаються, зверніться до свого провайдера облікового запису." "Цифри не збігаються" "Не вдалося встановити безпечне з\'єднання з новим пристроєм. Ваші наявні пристрої досі в безпеці, і вам не потрібно про них турбуватися." "Що тепер?" diff --git a/features/location/api/build.gradle.kts b/features/location/api/build.gradle.kts index ab85e37594..f8377389f1 100644 --- a/features/location/api/build.gradle.kts +++ b/features/location/api/build.gradle.kts @@ -71,6 +71,7 @@ dependencies { implementation(projects.libraries.matrixui) implementation(projects.libraries.uiStrings) implementation(libs.coil.compose) + implementation(libs.datetime) testCommonDependencies(libs) } diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt new file mode 100644 index 0000000000..8c53550737 --- /dev/null +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/LiveLocationSharingBanner.kt @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.api + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Button +import io.element.android.libraries.designsystem.theme.components.ButtonSize +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun LiveLocationSharingBanner( + onClick: () -> Unit, + onStopClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .background(ElementTheme.colors.bgCanvasDefault) + .drawBannerBorder(ElementTheme.colors.separatorPrimary) + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(12.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = CompoundIcons.LocationPinSolid(), + contentDescription = null, + tint = ElementTheme.colors.iconAccentPrimary, + modifier = Modifier.size(24.dp), + ) + Text( + text = stringResource(CommonStrings.screen_room_live_location_banner), + style = ElementTheme.typography.fontBodyMdMedium, + color = ElementTheme.colors.textPrimary, + ) + } + Button( + text = stringResource(CommonStrings.action_stop), + onClick = onStopClick, + destructive = true, + size = ButtonSize.Small, + ) + } +} + +private fun Modifier.drawBannerBorder(borderColor: Color): Modifier = drawBehind { + val strokeWidth = 1.dp.toPx() + val bottomY = size.height - strokeWidth / 2 + drawLine( + color = borderColor, + start = Offset(0f, strokeWidth / 2), + end = Offset(size.width, strokeWidth / 2), + strokeWidth = strokeWidth, + ) + drawLine( + color = borderColor, + start = Offset(0f, bottomY), + end = Offset(size.width, bottomY), + strokeWidth = strokeWidth, + ) +} + +@PreviewsDayNight +@Composable +internal fun LiveLocationSharingBannerPreview() = ElementPreview { + LiveLocationSharingBanner( + onClick = {}, + onStopClick = {}, + ) +} diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt new file mode 100644 index 0000000000..cd6b8731c1 --- /dev/null +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/live/ActiveLiveLocationShareManager.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.api.live + +import io.element.android.libraries.core.coroutine.mapState +import io.element.android.libraries.matrix.api.core.RoomId +import kotlinx.coroutines.flow.StateFlow +import kotlin.time.Duration + +interface ActiveLiveLocationShareManager { + /** All rooms currently sharing live location on this device. */ + val sharingRoomIds: StateFlow> + + /** + * Initializes the manager. + * This will restart or stop current location sharing and set the listener on the SDK + * and the session manager. + */ + suspend fun setup() + + /** + * Starts live location sharing in the given room. + * Calls room.startLiveLocationShare() on the SDK, registers the share, + * and starts the foreground GPS service if not already running. + */ + suspend fun startShare(roomId: RoomId, duration: Duration): Result + + /** + * Stops live location sharing in the given room. + * Calls room.stopLiveLocationShare() on the SDK, removes the share, + * and stops the foreground service if no shares remain. + */ + suspend fun stopShare(roomId: RoomId): Result +} + +fun ActiveLiveLocationShareManager.isCurrentlySharing(roomId: RoomId): StateFlow { + return sharingRoomIds.mapState { roomId in it } +} diff --git a/features/location/impl/build.gradle.kts b/features/location/impl/build.gradle.kts index 0da54a1394..165c32b7c5 100644 --- a/features/location/impl/build.gradle.kts +++ b/features/location/impl/build.gradle.kts @@ -37,10 +37,16 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.matrixui) implementation(projects.services.analytics.api) + implementation(projects.services.appnavstate.api) implementation(libs.accompanist.permission) implementation(projects.libraries.uiStrings) implementation(projects.libraries.featureflag.api) implementation(projects.libraries.dateformatter.api) + implementation(projects.libraries.preferences.api) + implementation(projects.libraries.push.api) + implementation(projects.libraries.sessionStorage.api) + implementation(libs.androidx.datastore.preferences) + implementation(libs.datetime) testCommonDependencies(libs, true) testImplementation(projects.libraries.matrix.test) @@ -50,4 +56,7 @@ dependencies { testImplementation(projects.services.analytics.test) testImplementation(projects.features.messages.test) testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.libraries.preferences.test) + testImplementation(projects.libraries.sessionStorage.test) + testImplementation(projects.features.location.test) } diff --git a/features/location/impl/src/main/AndroidManifest.xml b/features/location/impl/src/main/AndroidManifest.xml index ae728c09e1..e92ca68077 100644 --- a/features/location/impl/src/main/AndroidManifest.xml +++ b/features/location/impl/src/main/AndroidManifest.xml @@ -9,4 +9,14 @@ + + + + + + + diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt index a0b0cd4734..f90793b775 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheck.kt @@ -16,13 +16,16 @@ sealed interface LocationConstraintsCheck { data object PermissionRationale : LocationConstraintsCheck data object PermissionDenied : LocationConstraintsCheck data object LocationServiceDisabled : LocationConstraintsCheck + data object NotEnoughPowerLevel : LocationConstraintsCheck } fun checkLocationConstraints( permissionsState: PermissionsState, locationActions: LocationActions, + sendLiveLocationPermissions: SendLiveLocationPermissions, ): LocationConstraintsCheck { return when { + !sendLiveLocationPermissions.hasAll -> LocationConstraintsCheck.NotEnoughPowerLevel permissionsState.isAnyGranted -> { if (locationActions.isLocationEnabled()) { LocationConstraintsCheck.Success @@ -41,5 +44,6 @@ fun LocationConstraintsCheck.toDialogState(): LocationConstraintsDialogState { LocationConstraintsCheck.PermissionRationale -> LocationConstraintsDialogState.PermissionRationale LocationConstraintsCheck.PermissionDenied -> LocationConstraintsDialogState.PermissionDenied LocationConstraintsCheck.LocationServiceDisabled -> LocationConstraintsDialogState.LocationServiceDisabled + LocationConstraintsCheck.NotEnoughPowerLevel -> LocationConstraintsDialogState.NotEnoughPowerLevel } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt new file mode 100644 index 0000000000..d1a9e32026 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/SendLiveLocationPermissions.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.common + +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions + +/** + * Permissions to send beacon and beacon_info events in the room. + */ +data class SendLiveLocationPermissions( + val canSendBeacon: Boolean, + val canSendBeaconInfo: Boolean, +) { + val hasAll = canSendBeaconInfo && canSendBeacon + + companion object { + val DEFAULT = SendLiveLocationPermissions(canSendBeacon = false, canSendBeaconInfo = false) + val GRANTED = SendLiveLocationPermissions(canSendBeacon = true, canSendBeaconInfo = true) + } +} + +fun RoomPermissions.sendLiveLocationPermissions(): SendLiveLocationPermissions { + return SendLiveLocationPermissions( + canSendBeaconInfo = canOwnUserSendState(StateEventType.BeaconInfo), + canSendBeacon = canOwnUserSendMessage(MessageEventType.Beacon), + ) +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt index 95f5129f91..334aebaee6 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationConstraintsDialog.kt @@ -10,6 +10,8 @@ package io.element.android.features.location.impl.common.ui import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.res.stringResource +import io.element.android.features.location.impl.R +import io.element.android.libraries.designsystem.components.dialogs.AlertDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.ui.strings.CommonStrings @@ -42,6 +44,10 @@ fun LocationConstraintsDialog( onDismiss = onDismiss, submitText = stringResource(CommonStrings.action_continue), ) + LocationConstraintsDialogState.NotEnoughPowerLevel -> AlertDialog( + content = stringResource(R.string.screen_share_location_live_location_missing_permissions), + onDismiss = onDismiss + ) } } @@ -51,4 +57,5 @@ sealed interface LocationConstraintsDialogState { data object PermissionRationale : LocationConstraintsDialogState data object PermissionDenied : LocationConstraintsDialogState data object LocationServiceDisabled : LocationConstraintsDialogState + data object NotEnoughPowerLevel : LocationConstraintsDialogState } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt index 3d7b8df618..24476e3c66 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/LocationShareRow.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -44,6 +45,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun LocationShareRow( item: LocationShareItem, onShareClick: () -> Unit, + onStopClick: () -> Unit, modifier: Modifier = Modifier, ) { Row( @@ -101,11 +103,24 @@ fun LocationShareRow( ) } } + if (item.canStopSharing) { + IconButton( + onClick = onStopClick, + colors = IconButtonDefaults.iconButtonColors( + containerColor = ElementTheme.colors.bgCriticalPrimary, + contentColor = ElementTheme.colors.iconOnSolidPrimary, + ) + ) { + Icon( + imageVector = CompoundIcons.Stop(), + contentDescription = stringResource(CommonStrings.action_stop), + ) + } + } IconButton(onClick = onShareClick) { Icon( imageVector = CompoundIcons.ShareAndroid(), contentDescription = stringResource(CommonStrings.action_share), - tint = ElementTheme.colors.iconPrimary, ) } } @@ -128,8 +143,10 @@ internal fun LocationShareRowPreview() = ElementPreview { formattedTimestamp = "Shared 1 min ago", isLive = true, assetType = AssetType.SENDER, - location = Location(0.0, 0.0) + location = Location(0.0, 0.0), + isOwnUser = true, ), + onStopClick = {}, onShareClick = {}, ) LocationShareRow( @@ -145,8 +162,10 @@ internal fun LocationShareRowPreview() = ElementPreview { isLive = false, assetType = AssetType.PIN, formattedTimestamp = "Shared 5 hours ago", - location = Location(0.0, 0.0) + location = Location(0.0, 0.0), + isOwnUser = false ), + onStopClick = {}, onShareClick = {}, ) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt index 8b89f77be4..589ed87c6f 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/UserLocationPuck.kt @@ -23,7 +23,7 @@ import org.maplibre.compose.location.UserLocationState import org.maplibre.compose.location.rememberAndroidLocationProvider import org.maplibre.compose.location.rememberNullLocationProvider import org.maplibre.compose.location.rememberUserLocationState -import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds @Composable fun UserLocationPuck( @@ -72,9 +72,9 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState rememberNullLocationProvider() } else { rememberAndroidLocationProvider( - updateInterval = 1.minutes, - desiredAccuracy = DesiredAccuracy.Balanced, - minDistanceMeters = 50f, + updateInterval = 5.seconds, + desiredAccuracy = DesiredAccuracy.High, + minDistanceMeters = 5f, ) } return rememberUserLocationState(locationProvider) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt similarity index 58% rename from libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt rename to features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt index 49b2c43bc7..ee70936160 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/PushBindings.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/di/LocationBindings.kt @@ -5,13 +5,13 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.libraries.push.impl.di +package io.element.android.features.location.impl.di import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesTo -import io.element.android.libraries.push.impl.push.FetchPushForegroundService +import io.element.android.features.location.impl.live.service.LiveLocationSharingService @ContributesTo(AppScope::class) -interface PushBindings { - fun inject(fetchPushForegroundService: FetchPushForegroundService) +interface LocationBindings { + fun inject(service: LiveLocationSharingService) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt new file mode 100644 index 0000000000..fd16bea515 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManager.kt @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn +import dev.zacsweers.metro.binding +import io.element.android.features.location.api.Location +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.features.location.impl.live.service.LiveLocationReceiver +import io.element.android.features.location.impl.live.service.LiveLocationSharingCoordinator +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.location.BeaconId +import io.element.android.libraries.matrix.api.room.location.LiveLocationException +import io.element.android.libraries.sessionstorage.api.observer.SessionListener +import io.element.android.libraries.sessionstorage.api.observer.SessionObserver +import io.element.android.services.toolbox.api.systemclock.SystemClock +import kotlinx.coroutines.Job +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.getAndUpdate +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import timber.log.Timber +import java.util.concurrent.ConcurrentHashMap +import kotlin.concurrent.atomics.AtomicBoolean +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlin.time.Duration +import kotlin.time.Instant + +@OptIn(ExperimentalAtomicApi::class) +@SingleIn(SessionScope::class) +@ContributesBinding(SessionScope::class, binding = binding()) +class DefaultActiveLiveLocationShareManager( + private val matrixClient: MatrixClient, + private val coordinator: LiveLocationSharingCoordinator, + private val liveLocationStore: LiveLocationStore, + private val clock: SystemClock, + private val sessionObserver: SessionObserver, +) : ActiveLiveLocationShareManager, LiveLocationReceiver { + private val isSetup = AtomicBoolean(false) + private val cachedRooms = ConcurrentHashMap() + private val timeoutJobs = ConcurrentHashMap() + private val syncedActiveShareIds = MutableStateFlow>(emptySet()) + private val localSharingRoomIds = MutableStateFlow>(emptySet()) + override val sharingRoomIds: StateFlow> = localSharingRoomIds + + override suspend fun setup() = withContext(NonCancellable) { + if (isSetup.compareAndSet(expectedValue = false, newValue = true)) { + Timber.d("ActiveLiveLocationShareManager setup manager.") + + recoverPersistedShares() + + matrixClient.ownBeaconInfoUpdates + .onEach { update -> + Timber.d("Received beaconInfoUpdate:$update") + // First cancel the local share in this room if any. + if (update.roomId in localSharingRoomIds.value) { + stopLocalShare(roomId = update.roomId) + } + syncedActiveShareIds.update { + if (update.isLive) { + it + update.beaconId + } else { + it - update.beaconId + } + } + } + .launchIn(matrixClient.sessionCoroutineScope) + + sessionObserver.addListener(sessionListener) + } + } + + private val sessionListener: SessionListener = object : SessionListener { + override suspend fun onSessionDeleted(userId: String, wasLastSession: Boolean) { + if (matrixClient.sessionId.value == userId) { + clear() + } + } + } + + override suspend fun startShare(roomId: RoomId, duration: Duration): Result = withContext(NonCancellable) { + Timber.d("ActiveLiveLocationShareManager starting share for room $roomId with duration ${duration.inWholeSeconds}s") + val room = cachedRooms.getOrPut(roomId) { + matrixClient.getJoinedRoom(roomId) ?: return@withContext Result.failure(IllegalStateException("No room found for $roomId")) + } + // Before starting a new location share, stop the current one if any is active. + room.stopLiveLocationShare() + + room.startLiveLocationShare(duration.inWholeMilliseconds) + .onSuccess { beaconId -> + Timber.d("ActiveLiveLocationShareManager wait remote echo of $beaconId") + syncedActiveShareIds.first { beaconIds -> beaconIds.contains(beaconId) } + val expiresAt = Instant.fromEpochMilliseconds(clock.epochMillis() + duration.inWholeMilliseconds) + startLocalShare(roomId, expiresAt) + } + .onFailure { + Timber.e(it, "ActiveLiveLocationShareManager failed to start share for room $roomId") + stopLocalShare(roomId) + } + .map { } + } + + override suspend fun stopShare(roomId: RoomId): Result = withContext(NonCancellable) { + Timber.d("ActiveLiveLocationShareManager stopping share for room $roomId") + val room = cachedRooms.getOrPut(roomId) { + matrixClient.getJoinedRoom(roomId) ?: return@withContext Result.failure(IllegalStateException("No room found for $roomId")) + } + room.stopLiveLocationShare() + .onSuccess { + Timber.d("ActiveLiveLocationShareManager share stopped successfully for room $roomId") + } + .onFailure { + Timber.e(it, "ActiveLiveLocationShareManager failed to stop share for room $roomId") + } + .also { + stopLocalShare(roomId) + } + } + + override suspend fun onLocationUpdate(location: Location) { + val activeSharesCount = localSharingRoomIds.value.size + Timber.d("ActiveLiveLocationShareManager received location update for $activeSharesCount active share(s)") + localSharingRoomIds.value.forEach { roomId -> + Timber.d("ActiveLiveLocationShareManager sending location to room $roomId") + sendLiveLocation(roomId, location) + .onFailure { + Timber.e(it, "ActiveLiveLocationShareManager failed to send location to room $roomId") + } + } + } + + private suspend fun sendLiveLocation(roomId: RoomId, location: Location): Result { + val room = cachedRooms.getOrPut(roomId) { + matrixClient.getJoinedRoom(roomId) ?: return Result.failure(IllegalStateException("No room found for $roomId")) + } + return room.sendLiveLocation(location.toGeoUri()) + .recoverCatching { exception -> + when (exception) { + is LiveLocationException.NotLive -> { + stopLocalShare(roomId) + throw exception + } + else -> throw exception + } + } + } + + private suspend fun startLocalShare(roomId: RoomId, expiresAt: Instant) { + val wasEmpty = localSharingRoomIds.value.isEmpty() + Timber.d("ActiveLiveLocationShareManager share started successfully for room $roomId (wasEmpty=$wasEmpty)") + localSharingRoomIds.update { it + roomId } + liveLocationStore.setLiveLocationExpiry(roomId, expiresAt) + scheduleTimeout(roomId, expiresAt) + if (wasEmpty) { + Timber.d("ActiveLiveLocationShareManager registering with coordinator for session ${matrixClient.sessionId}") + coordinator.register(matrixClient.sessionId, this@DefaultActiveLiveLocationShareManager) + } + } + + private suspend fun recoverPersistedShares() { + val now = Instant.fromEpochMilliseconds(clock.epochMillis()) + liveLocationStore.getLiveLocationExpiries().forEach { (roomId, expiresAt) -> + if (expiresAt > now) { + // Only starts locally as the share is already started remotely + startLocalShare(roomId, expiresAt) + } else { + // Explicitly stop the share on the server. + stopShare(roomId) + } + } + } + + private fun scheduleTimeout(roomId: RoomId, expiresAt: Instant) { + timeoutJobs.remove(roomId)?.cancel() + val delayMillis = expiresAt.toEpochMilliseconds() - clock.epochMillis() + timeoutJobs[roomId] = matrixClient.sessionCoroutineScope.launch { + delay(delayMillis) + stopShare(roomId) + .onFailure { error -> + Timber.e(error, "ActiveLiveLocationShareManager failed to stop timed out share for room $roomId") + } + } + } + + private suspend fun stopLocalShare(roomId: RoomId) { + Timber.d("ActiveLiveLocationShareManager stop local share in $roomId") + timeoutJobs.remove(roomId)?.cancel() + val wasSharing = localSharingRoomIds.getAndUpdate { it - roomId }.isNotEmpty() + cachedRooms.remove(roomId)?.close() + liveLocationStore.removeLiveLocationExpiry(roomId) + if (wasSharing && localSharingRoomIds.value.isEmpty()) { + Timber.d("ActiveLiveLocationShareManager unregistering from coordinator for session ${matrixClient.sessionId}") + coordinator.unregister(matrixClient.sessionId) + } + } + + private suspend fun clear() { + Timber.d("ActiveLiveLocationShareManager clear state") + sessionObserver.removeListener(sessionListener) + coordinator.unregister(matrixClient.sessionId) + liveLocationStore.clear() + for (room in cachedRooms.values) { + room.close() + timeoutJobs[room.roomId]?.cancel() + } + timeoutJobs.clear() + cachedRooms.clear() + localSharingRoomIds.value = emptySet() + syncedActiveShareIds.value = emptySet() + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt new file mode 100644 index 0000000000..417d9d423a --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/LiveLocationStore.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringSetPreferencesKey +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.androidutils.hash.hash +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import kotlinx.coroutines.flow.first +import timber.log.Timber +import kotlin.time.Instant + +private const val LIVE_LOCATION_EXPIRY_VALUE_SEPARATOR = "=" + +@Inject +@SingleIn(SessionScope::class) +class LiveLocationStore( + preferenceDataStoreFactory: PreferenceDataStoreFactory, + sessionId: SessionId, +) { + private val store = preferenceDataStoreFactory.create("location_${sessionId.value.hash().take(16)}") + private val acceptedLiveLocationDisclaimerKey = booleanPreferencesKey("live_location_disclaimer_accepted") + private val liveLocationExpiriesKey = stringSetPreferencesKey("live_location_expiries") + + suspend fun hasAcceptedLiveLocationDisclaimer(): Boolean = runCatchingExceptions { + store.data.first()[acceptedLiveLocationDisclaimerKey] ?: false + }.getOrDefault(false) + + suspend fun setAcceptedLiveLocationDisclaimer(): Result = runCatchingExceptions { + store.edit { prefs -> + prefs[acceptedLiveLocationDisclaimerKey] = true + } + } + + suspend fun getLiveLocationExpiries(): Map = runCatchingExceptions { + val serialized = store.data.first()[liveLocationExpiriesKey].orEmpty() + decodeLiveLocationExpiries(serialized) + }.onFailure { error -> + Timber.e(error, "Failed to decode live location expiry payload") + }.getOrDefault(emptyMap()) + + suspend fun setLiveLocationExpiry(roomId: RoomId, expiresAt: Instant): Result = runCatchingExceptions { + store.edit { prefs -> + val current = decodeLiveLocationExpiries(prefs[liveLocationExpiriesKey].orEmpty()) + prefs[liveLocationExpiriesKey] = encodeLiveLocationExpiries(current + (roomId to expiresAt)) + } + } + + suspend fun removeLiveLocationExpiry(roomId: RoomId): Result = runCatchingExceptions { + store.edit { prefs -> + val current = decodeLiveLocationExpiries(prefs[liveLocationExpiriesKey].orEmpty()) + val updated = current - roomId + if (updated.isEmpty()) { + prefs.remove(liveLocationExpiriesKey) + } else { + prefs[liveLocationExpiriesKey] = encodeLiveLocationExpiries(updated) + } + } + } + + private fun decodeLiveLocationExpiries(serialized: Set): Map { + return runCatchingExceptions { + serialized + .map { it.split(LIVE_LOCATION_EXPIRY_VALUE_SEPARATOR) } + .associate { values -> + val roomId = RoomId(values[0]) + val expiresAtMillis = values[1].toLong() + roomId to Instant.fromEpochMilliseconds(expiresAtMillis) + } + }.getOrDefault(emptyMap()) + } + + private fun encodeLiveLocationExpiries(expiries: Map): Set { + return expiries.entries.map { (roomId, expiresAt) -> + "${roomId.value}$LIVE_LOCATION_EXPIRY_VALUE_SEPARATOR${expiresAt.toEpochMilliseconds()}" + }.toSet() + } + + suspend fun clear() { + store.edit { prefs -> prefs.clear() } + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt new file mode 100644 index 0000000000..9d4c461b0e --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/notification/LiveLocationSharingNotificationCreator.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.notification + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import androidx.annotation.ChecksSdkIntAtLeast +import androidx.annotation.RequiresApi +import androidx.core.app.NotificationCompat +import dev.zacsweers.metro.Inject +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.ui.strings.CommonStrings + +@Inject +class LiveLocationSharingNotificationCreator( + @ApplicationContext private val context: Context, + private val buildMeta: BuildMeta, +) { + companion object { + const val CHANNEL_ID = "LIVE_LOCATION_SHARING" + } + + fun createNotification(): Notification { + if (supportNotificationChannels()) { + ensureChannelExists() + } + return NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(android.R.drawable.ic_menu_mylocation) + .setContentTitle(context.getString(CommonStrings.live_location_sharing_foreground_service_title_android, buildMeta.applicationName)) + .setContentText(context.getString(CommonStrings.live_location_sharing_foreground_service_message_android)) + .setOngoing(true) + .build() + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun ensureChannelExists() { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (notificationManager.getNotificationChannel(CHANNEL_ID) == null) { + notificationManager.createNotificationChannel( + NotificationChannel( + CHANNEL_ID, + context.getString(CommonStrings.live_location_sharing_foreground_service_channel_title_android) + .ifEmpty { "Live Location Sharing" }, + NotificationManager.IMPORTANCE_LOW, + ) + ) + } + } + + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O) + private fun supportNotificationChannels() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt new file mode 100644 index 0000000000..adba75730c --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationReceiver.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.service + +import io.element.android.features.location.api.Location + +fun interface LiveLocationReceiver { + suspend fun onLocationUpdate(location: Location) +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt new file mode 100644 index 0000000000..e39acb14e8 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingCoordinator.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.service + +import android.content.Context +import android.content.Intent +import androidx.core.content.ContextCompat +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.Inject +import dev.zacsweers.metro.SingleIn +import io.element.android.features.location.api.Location +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.services.toolbox.api.systemclock.SystemClock +import timber.log.Timber +import java.util.concurrent.ConcurrentHashMap +import kotlin.concurrent.atomics.AtomicLong +import kotlin.concurrent.atomics.AtomicReference +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlin.time.Duration.Companion.seconds + +private val THROTTLE_WINDOW = 3.seconds + +@OptIn(ExperimentalAtomicApi::class) +@SingleIn(AppScope::class) +class LiveLocationSharingCoordinator internal constructor( + private val startService: () -> Unit, + private val stopService: () -> Unit, + private val nowMillis: () -> Long, +) { + @Inject + constructor(@ApplicationContext context: Context, clock: SystemClock) : this( + startService = { + ContextCompat.startForegroundService(context, Intent(context, LiveLocationSharingService::class.java)) + }, + stopService = { + context.stopService(Intent(context, LiveLocationSharingService::class.java)) + }, + nowMillis = clock::epochMillis + ) + + private val receivers = ConcurrentHashMap() + + private val lastDispatchMillis = AtomicLong(0L) + private val lastKnownLocation = AtomicReference(null) + + suspend fun register(sessionId: SessionId, receiver: LiveLocationReceiver) { + val wasEmpty = receivers.isEmpty() + Timber.d("LiveLocationSharingCoordinator registering receiver for session $sessionId (wasEmpty=$wasEmpty)") + receivers[sessionId] = receiver + if (wasEmpty) { + Timber.d("LiveLocationSharingCoordinator starting service") + runCatchingExceptions(startService).onFailure { + Timber.e(it, "Failed to start live location sharing service") + } + } + lastKnownLocation.load()?.let { + dispatch(it) + } + } + + fun unregister(sessionId: SessionId) { + Timber.d("LiveLocationSharingCoordinator unregistering receiver for session $sessionId") + receivers.remove(sessionId) + if (receivers.isEmpty()) { + lastKnownLocation.store(null) + Timber.d("LiveLocationSharingCoordinator stopping service (no more receivers)") + runCatchingExceptions(stopService).onFailure { + Timber.e(it, "Failed to stop live location sharing service") + } + } + } + + suspend fun dispatch(location: Location) { + val currentTimeMillis = nowMillis() + val millisSincePrevious = currentTimeMillis - lastDispatchMillis.load() + if (millisSincePrevious < THROTTLE_WINDOW.inWholeMilliseconds) { + Timber.d("Received location before $THROTTLE_WINDOW, ignore.") + return + } + lastKnownLocation.store(location) + lastDispatchMillis.store(currentTimeMillis) + receivers.forEach { (sessionId, receiver) -> + Timber.d("Dispatch received location for session $sessionId ") + runCatchingExceptions { + receiver.onLocationUpdate(location) + }.onFailure { + Timber.e(it, "Failed to dispatch live location update for session $sessionId") + } + } + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt new file mode 100644 index 0000000000..4451febb19 --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/live/service/LiveLocationSharingService.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live.service + +import android.annotation.SuppressLint +import android.app.Service +import android.content.Intent +import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION +import android.os.IBinder +import androidx.core.app.ServiceCompat +import dev.zacsweers.metro.Inject +import io.element.android.features.location.impl.di.LocationBindings +import io.element.android.features.location.impl.live.notification.LiveLocationSharingNotificationCreator +import io.element.android.libraries.architecture.bindings +import io.element.android.libraries.core.coroutine.childScope +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.AppCoroutineScope +import io.element.android.libraries.preferences.api.store.AppPreferencesStore +import io.element.android.libraries.push.api.notifications.ForegroundServiceType +import io.element.android.libraries.push.api.notifications.NotificationIdProvider +import io.element.android.services.appnavstate.api.AppForegroundStateService +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import org.maplibre.compose.location.AndroidLocationProvider +import org.maplibre.compose.location.DesiredAccuracy +import timber.log.Timber +import kotlin.time.Duration.Companion.seconds +import io.element.android.features.location.api.Location as ApiLocation + +private const val UPDATE_INTERVAL_IN_SECOND = 10 + +class LiveLocationSharingService : Service() { + @Inject lateinit var coordinator: LiveLocationSharingCoordinator + @Inject lateinit var notificationCreator: LiveLocationSharingNotificationCreator + @Inject lateinit var appPreferencesStore: AppPreferencesStore + + @Inject lateinit var appForegroundStateService: AppForegroundStateService + + @AppCoroutineScope + @Inject lateinit var appCoroutineScope: CoroutineScope + private lateinit var coroutineScope: CoroutineScope + + override fun onBind(p0: Intent?): IBinder? = null + + @OptIn(FlowPreview::class) + @SuppressLint("InlinedApi") + override fun onCreate() { + super.onCreate() + Timber.d("LiveLocationSharingService onCreate") + runCatchingExceptions { + bindings().inject(this) + appForegroundStateService.updateIsSharingLiveLocation(true) + coroutineScope = appCoroutineScope.childScope(Dispatchers.Default, "LiveLocationSharingService") + val notificationId = NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.LIVE_LOCATION) + Timber.d("LiveLocationSharingService starting foreground service with notificationId=$notificationId") + ServiceCompat.startForeground( + // service = + this, + // id = + notificationId, + // notification = + notificationCreator.createNotification(), + // foregroundServiceType = + FOREGROUND_SERVICE_TYPE_LOCATION, + ) + startLocationUpdatesListener() + }.onFailure { + Timber.e(it, "Failed to start live location sharing service") + stopSelf() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) + private fun startLocationUpdatesListener() { + Timber.d("LiveLocationSharingService listening to location updates") + appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() + .flatMapLatest { minDistanceMeters -> + val locationProvider = AndroidLocationProvider( + context = applicationContext, + updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, + minDistanceMeters = minDistanceMeters.toFloat(), + desiredAccuracy = DesiredAccuracy.Balanced, + coroutineScope = coroutineScope + ) + locationProvider.location + } + .filterNotNull() + .map { location -> + ApiLocation( + lat = location.position.latitude, + lon = location.position.longitude, + accuracy = location.accuracy.toFloat(), + ) + } + .onEach(coordinator::dispatch) + .launchIn(coroutineScope) + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + Timber.d("LiveLocationSharingService onStartCommand startId=$startId") + return START_STICKY + } + + override fun onDestroy() { + Timber.d("LiveLocationSharingService onDestroy") + if (::coroutineScope.isInitialized) { + coroutineScope.cancel() + } + appForegroundStateService.updateIsSharingLiveLocation(false) + super.onDestroy() + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt index d9ebc8b5af..e560ce805f 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationEvent.kt @@ -17,7 +17,8 @@ sealed interface ShareLocationEvent { val isPinned: Boolean, ) : ShareLocationEvent - data object ShowLiveLocationDurationPicker : ShareLocationEvent + data object InitiateLiveLocationShare : ShareLocationEvent + data object AcceptLiveLocationDisclaimer : ShareLocationEvent data class StartLiveLocationShare(val duration: Duration) : ShareLocationEvent data object StartTrackingUserLocation : ShareLocationEvent diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt index 10fddf1e50..6c0d2120bc 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenter.kt @@ -21,17 +21,22 @@ import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.Composer +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.location.impl.common.LocationConstraintsCheck import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.SendLiveLocationPermissions import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.location.impl.common.checkLocationConstraints import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsPresenter import io.element.android.features.location.impl.common.permissions.PermissionsState +import io.element.android.features.location.impl.common.sendLiveLocationPermissions import io.element.android.features.location.impl.common.toDialogState -import io.element.android.features.location.impl.share.ShareLocationState.Dialog.Constraints +import io.element.android.features.location.impl.live.LiveLocationStore import io.element.android.features.messages.api.MessageComposerContext +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runUpdatingState import io.element.android.libraries.core.extensions.flatMap import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.dateformatter.api.DurationFormatter @@ -41,6 +46,7 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.location.AssetType +import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.services.analytics.api.AnalyticsService @@ -63,6 +69,8 @@ class ShareLocationPresenter( private val featureFlagService: FeatureFlagService, private val client: MatrixClient, private val durationFormatter: DurationFormatter, + private val liveLocationShareManager: ActiveLiveLocationShareManager, + private val liveLocationStore: LiveLocationStore, ) : Presenter { @AssistedFactory fun interface Factory { @@ -82,15 +90,39 @@ class ShareLocationPresenter( var dialogState: ShareLocationState.Dialog by remember { mutableStateOf(ShareLocationState.Dialog.None) } + val startLiveLocationAction = remember { mutableStateOf>(AsyncAction.Uninitialized) } val currentUser by client.userProfile.collectAsState() + val sendLiveLocationPermissions by room.permissionsAsState(SendLiveLocationPermissions.DEFAULT) { perms -> + perms.sendLiveLocationPermissions() + } val scope = rememberCoroutineScope() fun checkLocationConstraints() { - val locationConstraints = checkLocationConstraints(permissionsState, locationActions) - dialogState = Constraints(locationConstraints.toDialogState()) + // No need to check SendLiveLocationPermissions here + val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) + dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState()) trackUserPosition = locationConstraints is LocationConstraintsCheck.Success } + suspend fun computeLiveLocationDialogState(): ShareLocationState.Dialog { + val hasAcceptedDisclaimer = liveLocationStore.hasAcceptedLiveLocationDisclaimer() + val constraintsResult = checkLocationConstraints(permissionsState, locationActions, sendLiveLocationPermissions) + return when { + !hasAcceptedDisclaimer -> { + ShareLocationState.Dialog.LiveLocationDisclaimer + } + constraintsResult is LocationConstraintsCheck.Success -> { + val durations = LIVE_LOCATION_DURATIONS.map { + LiveLocationDuration(duration = it, formatted = durationFormatter.format(it)) + } + ShareLocationState.Dialog.LiveLocationDurations(durations.toImmutableList()) + } + else -> { + ShareLocationState.Dialog.Constraints(constraintsResult.toDialogState()) + } + } + } + LaunchedEffect(permissionsState.permissions) { checkLocationConstraints() } fun handleEvent(event: ShareLocationEvent) { @@ -109,20 +141,23 @@ class ShareLocationPresenter( locationActions.openLocationSettings() dialogState = ShareLocationState.Dialog.None } - ShareLocationEvent.ShowLiveLocationDurationPicker -> { - val constraintsResult = checkLocationConstraints(permissionsState, locationActions) - dialogState = if (constraintsResult is LocationConstraintsCheck.Success) { - val durations = LIVE_LOCATION_DURATIONS.map { - LiveLocationDuration(duration = it, formatted = durationFormatter.format(it)) + ShareLocationEvent.InitiateLiveLocationShare -> scope.launch { + dialogState = computeLiveLocationDialogState() + } + ShareLocationEvent.AcceptLiveLocationDisclaimer -> scope.launch { + liveLocationStore.setAcceptedLiveLocationDisclaimer() + .onSuccess { + dialogState = computeLiveLocationDialogState() } - ShareLocationState.Dialog.LiveLocationDurations(durations.toImmutableList()) - } else { - Constraints(constraintsResult.toDialogState()) - } } is ShareLocationEvent.StartLiveLocationShare -> scope.launch { dialogState = ShareLocationState.Dialog.None - // room.startLiveLocationShare(event.duration.inWholeMilliseconds) + startLiveLocationAction.runUpdatingState { + liveLocationShareManager.startShare( + roomId = room.roomId, + duration = event.duration, + ) + } } ShareLocationEvent.RequestPermissions -> { dialogState = ShareLocationState.Dialog.None @@ -136,8 +171,9 @@ class ShareLocationPresenter( dialogState = dialogState, trackUserLocation = trackUserPosition, hasLocationPermission = permissionsState.isAnyGranted, - canShareLiveLocation = isLiveLocationSharingEnabled, + canShareLiveLocation = isLiveLocationSharingEnabled && timelineMode.canShareLiveLocation(), appName = appName, + startLiveLocationAction = startLiveLocationAction.value, eventSink = ::handleEvent, ) } @@ -174,4 +210,9 @@ class ShareLocationPresenter( } } +private fun Timeline.Mode.canShareLiveLocation() = when (this) { + is Timeline.Mode.Thread -> false + else -> true +} + private fun generateBody(uri: String): String = "Location was shared at $uri" diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt index 8b1f494f1e..68598cba04 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationState.kt @@ -9,6 +9,7 @@ package io.element.android.features.location.impl.share import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList @@ -19,11 +20,13 @@ data class ShareLocationState( val hasLocationPermission: Boolean, val appName: String, val canShareLiveLocation: Boolean, + val startLiveLocationAction: AsyncAction, val eventSink: (ShareLocationEvent) -> Unit, ) { sealed interface Dialog { data object None : Dialog data class Constraints(val state: LocationConstraintsDialogState) : Dialog + data object LiveLocationDisclaimer : Dialog data class LiveLocationDurations(val durations: ImmutableList) : Dialog } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt index facef74346..ae1b765b6b 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationStateProvider.kt @@ -10,6 +10,7 @@ package io.element.android.features.location.impl.share import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.persistentListOf @@ -51,6 +52,18 @@ class ShareLocationStateProvider : PreviewParameterProvider trackUserPosition = true, hasLocationPermission = true, ), + aShareLocationState( + dialogState = ShareLocationState.Dialog.None, + trackUserPosition = true, + hasLocationPermission = true, + canShareLiveLocation = true, + ), + aShareLocationState( + dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, + trackUserPosition = true, + hasLocationPermission = true, + canShareLiveLocation = true, + ), aShareLocationState( dialogState = ShareLocationState.Dialog.LiveLocationDurations( persistentListOf( @@ -73,6 +86,7 @@ fun aShareLocationState( hasLocationPermission: Boolean = false, canShareLiveLocation: Boolean = false, appName: String = APP_NAME, + startLiveLocationAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (ShareLocationEvent) -> Unit = {}, ): ShareLocationState { return ShareLocationState( @@ -82,6 +96,7 @@ fun aShareLocationState( hasLocationPermission = hasLocationPermission, canShareLiveLocation = canShareLiveLocation, appName = appName, + startLiveLocationAction = startLiveLocationAction, eventSink = eventSink ) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt index 1e163f417d..e20ee3a7a5 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/share/ShareLocationView.kt @@ -29,7 +29,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp @@ -44,11 +43,16 @@ import io.element.android.features.location.impl.common.ui.LocationFloatingActio import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold import io.element.android.features.location.impl.common.ui.UserLocationPuck import io.element.android.features.location.impl.common.ui.rememberUserLocationState -import io.element.android.libraries.androidutils.system.toast +import io.element.android.features.location.impl.share.ShareLocationEvent.StartLiveLocationShare +import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.components.LocationPin import io.element.android.libraries.designsystem.components.PinVariant +import io.element.android.libraries.designsystem.components.async.AsyncIndicator +import io.element.android.libraries.designsystem.components.async.AsyncIndicatorHost +import io.element.android.libraries.designsystem.components.async.rememberAsyncIndicatorState import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ListDialog import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.list.RadioButtonListItem @@ -74,7 +78,6 @@ fun ShareLocationView( navigateUp: () -> Unit, modifier: Modifier = Modifier, ) { - val context = LocalContext.current when (val dialogState = state.dialogState) { ShareLocationState.Dialog.None -> Unit is ShareLocationState.Dialog.Constraints -> LocationConstraintsDialog( @@ -85,12 +88,17 @@ fun ShareLocationView( onOpenLocationSettings = { state.eventSink(ShareLocationEvent.OpenLocationSettings) }, onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) }, ) + ShareLocationState.Dialog.LiveLocationDisclaimer -> ConfirmationDialog( + content = stringResource(R.string.screen_share_location_live_location_disclaimer_title), + submitText = stringResource(CommonStrings.action_accept), + cancelText = stringResource(CommonStrings.action_decline), + onSubmitClick = { state.eventSink(ShareLocationEvent.AcceptLiveLocationDisclaimer) }, + onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) }, + ) is ShareLocationState.Dialog.LiveLocationDurations -> LiveLocationDurationDialog( durations = dialogState.durations, onSelectDuration = { duration -> - state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration)) - context.toast("Not implemented yet!") - navigateUp() + state.eventSink(StartLiveLocationShare(duration)) }, onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) }, ) @@ -160,10 +168,46 @@ fun ShareLocationView( .align(Alignment.TopEnd) .padding(all = 16.dp), ) + StartLiveLocationActionView(state.startLiveLocationAction, navigateUp) } ) } +@Composable +private fun StartLiveLocationActionView( + action: AsyncAction, + onActionSuccess: () -> Unit, + modifier: Modifier = Modifier, +) { + Box(modifier = modifier) { + val asyncIndicatorState = rememberAsyncIndicatorState() + AsyncIndicatorHost(state = asyncIndicatorState) + + when (action) { + is AsyncAction.Loading -> { + LaunchedEffect(action) { + asyncIndicatorState.enqueue { + AsyncIndicator.Loading(text = stringResource(CommonStrings.common_waiting_live_location)) + } + } + } + is AsyncAction.Failure -> { + LaunchedEffect(action) { + asyncIndicatorState.enqueue(AsyncIndicator.DURATION_SHORT) { + AsyncIndicator.Failure( + text = stringResource(CommonStrings.common_something_went_wrong), + ) + } + } + } + is AsyncAction.Success -> { + LaunchedEffect(action) { onActionSuccess() } + } + else -> Unit + } + } +} + @Composable private fun BottomSheetContent( cameraState: CameraState, @@ -202,7 +246,7 @@ private fun BottomSheetContent( } if (state.canShareLiveLocation) { ShareLiveLocationItem { - state.eventSink(ShareLocationEvent.ShowLiveLocationDurationPicker) + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) } } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt index 6a3e3521e0..34132dccf3 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationEvent.kt @@ -17,4 +17,5 @@ sealed interface ShowLocationEvent { data object RequestPermissions : ShowLocationEvent data object OpenAppSettings : ShowLocationEvent data object OpenLocationSettings : ShowLocationEvent + data object StopLocationSharing : ShowLocationEvent } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt index 43d3aa6d00..207b4b01dd 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt @@ -15,14 +15,17 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import io.element.android.features.location.api.Location import io.element.android.features.location.api.ShowLocationMode +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.location.impl.common.LocationConstraintsCheck import io.element.android.features.location.impl.common.MapDefaults +import io.element.android.features.location.impl.common.SendLiveLocationPermissions import io.element.android.features.location.impl.common.actions.LocationActions import io.element.android.features.location.impl.common.checkLocationConstraints import io.element.android.features.location.impl.common.permissions.PermissionsEvents @@ -45,6 +48,7 @@ import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.launch @AssistedInject class ShowLocationPresenter( @@ -55,6 +59,7 @@ class ShowLocationPresenter( private val dateFormatter: DateFormatter, private val stringProvider: StringProvider, private val joinedRoom: JoinedRoom, + private val liveLocationShareManager: ActiveLiveLocationShareManager, ) : Presenter { @AssistedFactory fun interface Factory { @@ -65,6 +70,7 @@ class ShowLocationPresenter( @Composable override fun present(): ShowLocationState { + val coroutineScope = rememberCoroutineScope() val permissionsState: PermissionsState = permissionsPresenter.present() var isTrackMyLocation by remember { mutableStateOf(false) } val appName by remember { derivedStateOf { buildMeta.applicationName } } @@ -85,7 +91,7 @@ class ShowLocationPresenter( } is ShowLocationEvent.TrackMyLocation -> { if (event.enabled) { - val locationConstraints = checkLocationConstraints(permissionsState, locationActions) + val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) isTrackMyLocation = locationConstraints is LocationConstraintsCheck.Success dialogState = locationConstraints.toDialogState() } else { @@ -102,6 +108,9 @@ class ShowLocationPresenter( dialogState = LocationConstraintsDialogState.None } ShowLocationEvent.RequestPermissions -> permissionsState.eventSink(PermissionsEvents.RequestPermissions) + ShowLocationEvent.StopLocationSharing -> coroutineScope.launch { + liveLocationShareManager.stopShare(joinedRoom.roomId) + } } } @@ -127,6 +136,7 @@ class ShowLocationPresenter( location = mode.location, isLive = false, assetType = mode.assetType, + isOwnUser = mode.senderId == joinedRoom.sessionId ) ) } @@ -163,6 +173,7 @@ class ShowLocationPresenter( location = location, isLive = true, assetType = lastLocation.assetType, + isOwnUser = share.userId == joinedRoom.sessionId ) } .toImmutableList() diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt index b6a60f35db..720697cbf7 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt @@ -38,7 +38,10 @@ data class LocationShareItem( val location: Location, val isLive: Boolean, val assetType: AssetType?, -) + val isOwnUser: Boolean +) { + val canStopSharing = isLive && isOwnUser +} fun LocationShareItem.toMarkerData(): LocationMarkerData { val pinVariant = if (assetType == AssetType.PIN) { diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt index 2bbf4ae34e..1c7b9a3160 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt @@ -81,6 +81,7 @@ fun aLocationShareItem( assetType: AssetType? = null, formattedTimestamp: String = "Shared 1 min ago", location: Location = Location(1.23, 2.34, 4f), + isOwnUser: Boolean = false, ) = LocationShareItem( userId = userId, displayName = displayName, @@ -89,4 +90,5 @@ fun aLocationShareItem( location = location, isLive = isLive, assetType = assetType, + isOwnUser = isOwnUser, ) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt index 7ac5946723..6766fa6424 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt @@ -147,6 +147,7 @@ fun ShowLocationView( LocationShareRow( item = locationShare, onShareClick = { state.eventSink(ShowLocationEvent.Share(locationShare.location)) }, + onStopClick = { state.eventSink(ShowLocationEvent.StopLocationSharing) }, modifier = Modifier.clickable { state.eventSink(ShowLocationEvent.TrackMyLocation(false)) val position = CameraPosition( diff --git a/features/location/impl/src/main/res/values-el/translations.xml b/features/location/impl/src/main/res/values-el/translations.xml new file mode 100644 index 0000000000..8ae7c58c74 --- /dev/null +++ b/features/location/impl/src/main/res/values-el/translations.xml @@ -0,0 +1,5 @@ + + + "Το ιστορικό ζωντανής τοποθεσίας σας θα αποθηκευτεί στην αίθουσα και θα είναι ορατό στα μέλη μετά το τέλος της συνεδρίας." + "Επιλέξτε για πόσο χρονικό διάστημα θα κοινοποιείτε την τρέχουσα τοποθεσία σας." + diff --git a/features/location/impl/src/main/res/values-et/translations.xml b/features/location/impl/src/main/res/values-et/translations.xml new file mode 100644 index 0000000000..53aede1bb2 --- /dev/null +++ b/features/location/impl/src/main/res/values-et/translations.xml @@ -0,0 +1,4 @@ + + + "Vali, kui kaua tahad oma reaalajas jagada." + diff --git a/features/location/impl/src/main/res/values-hu/translations.xml b/features/location/impl/src/main/res/values-hu/translations.xml index b89965485f..0ccb2a2413 100644 --- a/features/location/impl/src/main/res/values-hu/translations.xml +++ b/features/location/impl/src/main/res/values-hu/translations.xml @@ -2,4 +2,5 @@ "Az élő helymeghatározás története a szobában lesz tárolva, és a munkamenet befejezése után is látható marad a tagok számára." "Válassza ki, mennyi ideig szeretné megosztani az aktuális tartózkodási helyét." + "Nincs jogosultsága az élő tartózkodási helyének megosztására ebben a szobában." diff --git a/features/location/impl/src/main/res/values-it/translations.xml b/features/location/impl/src/main/res/values-it/translations.xml index 235a9eba4a..44adc1e3c5 100644 --- a/features/location/impl/src/main/res/values-it/translations.xml +++ b/features/location/impl/src/main/res/values-it/translations.xml @@ -2,4 +2,5 @@ "La cronologia delle tue posizioni in tempo reale verrà archiviata nella stanza e sarà visibile ai membri al termine della sessione." "Scegli per quanto tempo condividere la tua posizione in tempo reale." + "Non hai l\'autorizzazione per condividere la tua posizione in tempo reale in questa stanza" diff --git a/features/location/impl/src/main/res/values-pl/translations.xml b/features/location/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..c480d0f43b --- /dev/null +++ b/features/location/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,6 @@ + + + "Twoja historia lokalizacji na żywo zostanie zapisana w pokoju i będzie widoczna dla członków po zakończeniu sesji." + "Wybierz, jak długo chcesz udostępniać swoją lokalizację na żywo." + "Nie masz uprawnień do udostępniania swojej lokalizacji na żywo w tym pokoju" + diff --git a/features/location/impl/src/main/res/values-uk/translations.xml b/features/location/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..3c8155817a --- /dev/null +++ b/features/location/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,5 @@ + + + "Ваша історія поточного місцезнаходження зберігатиметься у кімнаті та буде доступна учасникам після завершення сеансу." + "Виберіть, як довго ділитися своїм місцезнаходженням." + diff --git a/features/location/impl/src/main/res/values-zh/translations.xml b/features/location/impl/src/main/res/values-zh/translations.xml index 6837d3a1eb..563bba593f 100644 --- a/features/location/impl/src/main/res/values-zh/translations.xml +++ b/features/location/impl/src/main/res/values-zh/translations.xml @@ -2,4 +2,5 @@ "你实时位置历史将存储在房间中,并于会话结束后对其他成员可见。" "选择共享实时位置的时长。" + "你无权在此房内共享实时位置。" diff --git a/features/location/impl/src/main/res/values/localazy.xml b/features/location/impl/src/main/res/values/localazy.xml index ac2ff4b2a0..975bb3c6ea 100644 --- a/features/location/impl/src/main/res/values/localazy.xml +++ b/features/location/impl/src/main/res/values/localazy.xml @@ -2,4 +2,5 @@ "Your live location history will be stored in the room and visible to members after the session ends." "Choose how long to share your live location." + "You do not have permissions to share your live location in this room" diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt index c8e1f21a48..debe95b464 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/LocationConstraintsCheckTest.kt @@ -21,7 +21,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.Success) } @@ -33,7 +33,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.Success) } @@ -45,7 +45,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = false) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.LocationServiceDisabled) } @@ -58,7 +58,7 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.PermissionRationale) } @@ -71,8 +71,20 @@ class LocationConstraintsCheckTest { ) val locationActions = FakeLocationActions(isLocationEnabled = true) - val result = checkLocationConstraints(permissionsState, locationActions) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) assertThat(result).isEqualTo(LocationConstraintsCheck.PermissionDenied) } + + @Test + fun `checkLocationConstraints returns NotEnoughPowerLevel when send permissions are not granted`() { + val permissionsState = aPermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = false, + ) + val locationActions = FakeLocationActions(isLocationEnabled = true) + val result = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.DEFAULT) + + assertThat(result).isEqualTo(LocationConstraintsCheck.NotEnoughPowerLevel) + } } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt new file mode 100644 index 0000000000..85f0e1c33f --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/DefaultActiveLiveLocationShareManagerTest.kt @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.emptyPreferences +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.live.service.LiveLocationSharingCoordinator +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID_2 +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory +import io.element.android.libraries.sessionstorage.api.observer.SessionObserver +import io.element.android.libraries.sessionstorage.test.observer.FakeSessionObserver +import io.element.android.services.toolbox.api.systemclock.SystemClock +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.async +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Instant + +@OptIn(ExperimentalCoroutinesApi::class) +class DefaultActiveLiveLocationShareManagerTest { + @get:Rule + val warmUpRule = WarmUpRule() + + @Test + fun `starting the first share starts the coordinator service after the beacon echo and adds an active share`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder + ) + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val room = FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { givenGetRoomResult(A_ROOM_ID, room) }, + coordinator = coordinator, + clock = FakeSystemClock(epochMillisResult = 123L), + ) + advanceUntilIdle() + + val result = async { manager.startShare(A_ROOM_ID, 60.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + + assertThat(result.await().isSuccess).isTrue() + assertThat(manager.sharingRoomIds.value).containsExactly(A_ROOM_ID) + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isNeverCalled() + } + + @Test + fun `stopping the last share stops the coordinator service`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder + ) + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val room = FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { givenGetRoomResult(A_ROOM_ID, room) }, + coordinator = coordinator, + ) + advanceUntilIdle() + + val startResult = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + val result = manager.stopShare(A_ROOM_ID) + + assertThat(result.isSuccess).isTrue() + assertThat(manager.sharingRoomIds.value).isEmpty() + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isCalledOnce() + } + + @Test + fun `two managers with the same room id keep isolated state per session`() = runTest { + val coordinator = createCoordinator() + val beaconInfoUpdatesOne = MutableSharedFlow(replay = 1) + val beaconInfoUpdatesTwo = MutableSharedFlow(replay = 1) + val managerOne = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdatesOne, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + ) + val managerTwo = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID_2, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdatesTwo, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + ) + advanceUntilIdle() + + val startResult = async { managerOne.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdatesOne.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + assertThat(managerOne.sharingRoomIds.value).containsExactly(A_ROOM_ID) + assertThat(managerTwo.sharingRoomIds.value).isEmpty() + } + + @Test + fun `start share persists room expiry after beacon echo`() = runTest { + val liveLocationStore = createLiveLocationStore() + val coordinator = createCoordinator() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 123L), + ) + advanceUntilIdle() + + val result = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + + assertThat(result.await().isSuccess).isTrue() + assertThat(liveLocationStore.getLiveLocationExpiries()).containsKey(A_ROOM_ID) + } + + @Test + fun `stop share removes persisted expiry`() = runTest { + val liveLocationStore = createLiveLocationStore() + val coordinator = createCoordinator() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = coordinator, + liveLocationStore = liveLocationStore, + ) + advanceUntilIdle() + + val startResult = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + manager.stopShare(A_ROOM_ID) + + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + } + + @Test + fun `setup restores unexpired stored share and registers coordinator`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val liveLocationStore = createLiveLocationStore().apply { + setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(10_000L)) + } + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult(A_ROOM_ID, FakeJoinedRoom()) + }, + coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder, + ), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 1_000L), + ) + + assertThat(manager.sharingRoomIds.value).containsExactly(A_ROOM_ID) + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isNeverCalled() + } + + @Test + fun `setup remotely stops expired stored share and removes it from store`() = runTest { + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val liveLocationStore = createLiveLocationStore().apply { + setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)) + } + createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom(stopLiveLocationShareResult = stopLiveLocationShareResult), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 5_000L), + ) + advanceUntilIdle() + assert(stopLiveLocationShareResult).isCalledOnce() + assertThat(liveLocationStore.getLiveLocationExpiries()).isEmpty() + } + + @Test + fun `stop share closes loaded room and removes persisted expiry when room is not tracked`() = runTest { + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val room = FakeJoinedRoom(stopLiveLocationShareResult = stopLiveLocationShareResult) + val liveLocationStore = createInMemoryLiveLocationStore() + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult(A_ROOM_ID, room) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + ) + liveLocationStore.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(10_000L)) + + val result = manager.stopShare(A_ROOM_ID) + + assertThat(result.isSuccess).isTrue() + assert(stopLiveLocationShareResult).isCalledOnce() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + room.baseRoom.assertDestroyed() + } + + @Test + fun `share is automatically stopped when timeout elapses`() = runTest { + val liveLocationStore = createInMemoryLiveLocationStore() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val stopLiveLocationShareResult = lambdaRecorder> { Result.success(Unit) } + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = stopLiveLocationShareResult + ), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 123L), + ) + advanceUntilIdle() + + val startResult = async { manager.startShare(A_ROOM_ID, 1.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(startResult.await().isSuccess).isTrue() + + manager.sharingRoomIds.test { + assertThat(awaitItem()).containsExactly(A_ROOM_ID) + assertThat(awaitItem()).isEmpty() + advanceUntilIdle() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(stopLiveLocationShareResult).isCalledExactly(2) + } + } + + @Test + fun `restored share is automatically stopped when remaining timeout elapses`() = runTest { + val liveLocationStore = createInMemoryLiveLocationStore().apply { + setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(6_000L)) + } + val stopLiveLocationShareLambda = lambdaRecorder> { Result.success(Unit) } + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + stopLiveLocationShareResult = stopLiveLocationShareLambda + ), + ) + }, + coordinator = createCoordinator(), + liveLocationStore = liveLocationStore, + clock = FakeSystemClock(epochMillisResult = 1_000L), + ) + + manager.sharingRoomIds.test { + assertThat(awaitItem()).containsExactly(A_ROOM_ID) + assertThat(awaitItem()).isEmpty() + advanceUntilIdle() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(stopLiveLocationShareLambda).isCalledOnce() + } + } + + @Test + fun `session deleted clears local state`() = runTest { + val startServiceRecorder = lambdaRecorder { } + val stopServiceRecorder = lambdaRecorder { } + val liveLocationStore = createInMemoryLiveLocationStore() + val sessionObserver = FakeSessionObserver() + val beaconInfoUpdates = MutableSharedFlow(replay = 1) + val manager = createManager( + client = FakeMatrixClient( + sessionId = A_SESSION_ID, + sessionCoroutineScope = backgroundScope, + ownBeaconInfoUpdates = beaconInfoUpdates, + ).apply { + givenGetRoomResult( + A_ROOM_ID, + FakeJoinedRoom( + startLiveLocationShareResult = { Result.success(AN_EVENT_ID) }, + stopLiveLocationShareResult = { Result.success(Unit) }, + ), + ) + }, + coordinator = createCoordinator( + startService = startServiceRecorder, + stopService = stopServiceRecorder, + ), + liveLocationStore = liveLocationStore, + sessionObserver = sessionObserver, + ) + advanceUntilIdle() + + val firstStart = async { manager.startShare(A_ROOM_ID, 15.minutes) } + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(firstStart.await().isSuccess).isTrue() + + sessionObserver.onSessionDeleted(A_SESSION_ID.value) + advanceUntilIdle() + + assertThat(manager.sharingRoomIds.value).isEmpty() + assertThat(liveLocationStore.getLiveLocationExpiries()).doesNotContainKey(A_ROOM_ID) + assert(startServiceRecorder).isCalledOnce() + assert(stopServiceRecorder).isCalledOnce() + + val secondStart = async { manager.startShare(A_ROOM_ID, 15.minutes) } + advanceUntilIdle() + assertThat(secondStart.isCompleted).isFalse() + + beaconInfoUpdates.emit(BeaconInfoUpdate(roomId = A_ROOM_ID, beaconId = AN_EVENT_ID, isLive = true)) + assertThat(secondStart.await().isSuccess).isTrue() + } + + private suspend fun createManager( + client: FakeMatrixClient = FakeMatrixClient(sessionId = A_SESSION_ID), + coordinator: LiveLocationSharingCoordinator = createCoordinator(), + liveLocationStore: LiveLocationStore = createLiveLocationStore(), + clock: SystemClock = FakeSystemClock(), + sessionObserver: SessionObserver = FakeSessionObserver(), + ): DefaultActiveLiveLocationShareManager { + return DefaultActiveLiveLocationShareManager( + matrixClient = client, + coordinator = coordinator, + liveLocationStore = liveLocationStore, + clock = clock, + sessionObserver = sessionObserver, + ).apply { + setup() + } + } + + private fun createCoordinator( + startService: () -> Unit = {}, + stopService: () -> Unit = {}, + nowMillis: () -> Long = { 0L }, + ): LiveLocationSharingCoordinator { + return LiveLocationSharingCoordinator( + startService = startService, + stopService = stopService, + nowMillis = nowMillis, + ) + } + + private fun createLiveLocationStore( + sessionId: io.element.android.libraries.matrix.api.core.SessionId = A_SESSION_ID, + preferenceDataStoreFactory: PreferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + ): LiveLocationStore { + return LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = sessionId, + ) + } + + private fun createInMemoryLiveLocationStore( + sessionId: io.element.android.libraries.matrix.api.core.SessionId = A_SESSION_ID, + ): LiveLocationStore { + val preferenceDataStoreFactory = object : PreferenceDataStoreFactory { + override fun create(name: String): DataStore { + var preferences: Preferences = emptyPreferences() + return object : DataStore { + override val data: Flow + get() = flowOf(preferences) + + override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences { + preferences = transform(preferences) + return preferences + } + } + } + } + return createLiveLocationStore( + sessionId = sessionId, + preferenceDataStoreFactory = preferenceDataStoreFactory, + ) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt new file mode 100644 index 0000000000..f74322b4c5 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/live/LiveLocationSharingCoordinatorTest.kt @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.live + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.Location +import io.element.android.features.location.impl.live.service.LiveLocationReceiver +import io.element.android.features.location.impl.live.service.LiveLocationSharingCoordinator +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID_2 +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class LiveLocationSharingCoordinatorTest { + @Test + fun `first registration starts the service and last unregister stops it`() = runTest { + var startCount = 0 + var stopCount = 0 + val coordinator = LiveLocationSharingCoordinator( + startService = { startCount++ }, + stopService = { stopCount++ }, + nowMillis = { 0L }, + ) + + coordinator.register(A_SESSION_ID, LiveLocationReceiver { }) + coordinator.unregister(A_SESSION_ID) + + assertThat(startCount).isEqualTo(1) + assertThat(stopCount).isEqualTo(1) + } + + @Test + fun `dispatch isolates receiver failures and still reaches later receivers`() = runTest { + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { 4_000L }, + ) + + coordinator.register(A_SESSION_ID) { error("boom") } + coordinator.register(A_SESSION_ID_2) { location -> delivered += location } + coordinator.dispatch(Location(lat = 1.0, lon = 2.0, accuracy = 3f)) + + assertThat(delivered).containsExactly(Location(lat = 1.0, lon = 2.0, accuracy = 3f)) + } + + @Test + fun `dispatch delivers first location immediately`() = runTest { + var nowMillis = 4_000L + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { nowMillis }, + ) + + coordinator.register(A_SESSION_ID) { location -> delivered += location } + + val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) + + coordinator.dispatch(firstLocation) + + assertThat(delivered).containsExactly(firstLocation) + } + + @Test + fun `dispatch drops updates inside the throttle window`() = runTest { + var nowMillis = 4_000L + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { nowMillis }, + ) + + coordinator.register(A_SESSION_ID) { location -> delivered += location } + + val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) + val secondLocation = Location(lat = 4.0, lon = 5.0, accuracy = 6f) + + coordinator.dispatch(firstLocation) + nowMillis += 500 + coordinator.dispatch(secondLocation) + + assertThat(delivered).containsExactly(firstLocation) + } + + @Test + fun `dispatch delivers next update after the throttle window elapses`() = runTest { + var nowMillis = 4_000L + val delivered = mutableListOf() + val coordinator = LiveLocationSharingCoordinator( + startService = { }, + stopService = { }, + nowMillis = { nowMillis }, + ) + + coordinator.register(A_SESSION_ID) { location -> delivered += location } + + val firstLocation = Location(lat = 1.0, lon = 2.0, accuracy = 3f) + val secondLocation = Location(lat = 4.0, lon = 5.0, accuracy = 6f) + + coordinator.dispatch(firstLocation) + nowMillis += 3_000 + coordinator.dispatch(secondLocation) + + assertThat(delivered).containsExactly(firstLocation, secondLocation).inOrder() + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt index edd000e02c..9b1a14fb51 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/DefaultShareLocationEntryPointTest.kt @@ -13,6 +13,8 @@ import com.bumble.appyx.core.modality.BuildContext import com.google.common.truth.Truth.assertThat import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.features.location.impl.live.LiveLocationStore +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter import io.element.android.libraries.featureflag.test.FakeFeatureFlagService @@ -20,8 +22,10 @@ import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -30,16 +34,17 @@ class DefaultShareLocationEntryPointTest { val instantTaskExecutorRule = InstantTaskExecutorRule() @Test - fun `test node builder`() { + fun `test node builder`() = runTest { val entryPoint = DefaultShareLocationEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> + val room = FakeJoinedRoom() ShareLocationNode( buildContext = buildContext, plugins = plugins, presenterFactory = { timelineMode: Timeline.Mode -> ShareLocationPresenter( permissionsPresenterFactory = { FakePermissionsPresenter() }, - room = FakeJoinedRoom(), + room = room, timelineMode = timelineMode, analyticsService = FakeAnalyticsService(), messageComposerContext = FakeMessageComposerContext(), @@ -48,6 +53,11 @@ class DefaultShareLocationEntryPointTest { featureFlagService = FakeFeatureFlagService(), client = FakeMatrixClient(), durationFormatter = FakeDurationFormatter(), + liveLocationShareManager = FakeActiveLiveLocationShareManager(), + liveLocationStore = LiveLocationStore( + preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + sessionId = room.sessionId, + ), ) }, analyticsService = FakeAnalyticsService(), diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt index 46bc4a55df..dff5f05ee9 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationPresenterTest.kt @@ -10,6 +10,9 @@ package io.element.android.features.location.impl.share +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.emptyPreferences import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test @@ -22,28 +25,48 @@ import io.element.android.features.location.impl.common.permissions.FakePermissi import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.impl.live.LiveLocationStore +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.test.FakeMessageComposerContext import io.element.android.libraries.dateformatter.test.FakeDurationFormatter +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.MessageEventType +import io.element.android.libraries.matrix.api.room.StateEventType import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.matrix.test.A_THREAD_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.libraries.matrix.test.room.FakeBaseRoom import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions import io.element.android.libraries.matrix.test.timeline.FakeTimeline +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration +import kotlin.time.Duration.Companion.hours class ShareLocationPresenterTest { @get:Rule @@ -59,13 +82,16 @@ class ShareLocationPresenterTest { private val durationFormatter = FakeDurationFormatter() - private fun createShareLocationPresenter( + private fun TestScope.createShareLocationPresenter( joinedRoom: JoinedRoom = FakeJoinedRoom(), + timelineMode: Timeline.Mode = Timeline.Mode.Live, locationActions: FakeLocationActions = fakeLocationActions, + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), + liveLocationStore: LiveLocationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId), ): ShareLocationPresenter = ShareLocationPresenter( permissionsPresenterFactory = { fakePermissionsPresenter }, room = joinedRoom, - timelineMode = Timeline.Mode.Live, + timelineMode = timelineMode, analyticsService = fakeAnalyticsService, messageComposerContext = fakeMessageComposerContext, locationActions = locationActions, @@ -73,6 +99,8 @@ class ShareLocationPresenterTest { featureFlagService = fakeFeatureFlagService, client = fakeMatrixClient, durationFormatter = durationFormatter, + liveLocationShareManager = liveLocationShareManager, + liveLocationStore = liveLocationStore, ) @Test @@ -296,7 +324,15 @@ class ShareLocationPresenterTest { @Test fun `ShowLiveLocationDurationPicker shows duration dialog when constraints pass`() = runTest { - val shareLocationPresenter = createShareLocationPresenter() + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId).apply { + setAcceptedLiveLocationDisclaimer().getOrThrow() + } + val shareLocationPresenter = createShareLocationPresenter(joinedRoom = joinedRoom, liveLocationStore = locationStore) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.AllGranted, @@ -307,7 +343,7 @@ class ShareLocationPresenterTest { shareLocationPresenter.test { skipItems(1) val initialState = awaitItem() - initialState.eventSink(ShareLocationEvent.ShowLiveLocationDurationPicker) + initialState.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val durationDialogState = awaitItem() assertThat(durationDialogState.dialogState).isInstanceOf(ShareLocationState.Dialog.LiveLocationDurations::class.java) @@ -315,9 +351,155 @@ class ShareLocationPresenterTest { } } + @Test + fun `ShowLiveLocationDurationPicker shows disclaimer when acceptance is missing`() = runTest { + val presenter = createShareLocationPresenter() + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val dialogState = awaitItem() + + assertThat(dialogState.dialogState).isEqualTo(ShareLocationState.Dialog.LiveLocationDisclaimer) + } + } + + @Test + fun `AcceptLiveLocationDisclaimer persists acceptance and shows durations`() = runTest { + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId) + val presenter = createShareLocationPresenter(joinedRoom = joinedRoom, liveLocationStore = locationStore) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + awaitItem() + + state.eventSink(ShareLocationEvent.AcceptLiveLocationDisclaimer) + val durationState = awaitItem() + + assertThat(locationStore.hasAcceptedLiveLocationDisclaimer()).isTrue() + assertThat(durationState.dialogState).isInstanceOf(ShareLocationState.Dialog.LiveLocationDurations::class.java) + } + } + + @Test + fun `AcceptLiveLocationDisclaimer keeps disclaimer gate active when persistence fails`() = runTest { + val joinedRoom = FakeJoinedRoom() + val presenter = createShareLocationPresenter( + joinedRoom = joinedRoom, + liveLocationStore = createFailingLiveLocationStore(sessionId = joinedRoom.sessionId), + ) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val disclaimerState = awaitItem() + + disclaimerState.eventSink(ShareLocationEvent.AcceptLiveLocationDisclaimer) + advanceUntilIdle() + + expectNoEvents() + } + } + + @Test + fun `ShowLiveLocationDurationPicker bypasses disclaimer when already accepted`() = runTest { + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId).apply { + setAcceptedLiveLocationDisclaimer().getOrThrow() + } + val presenter = createShareLocationPresenter(joinedRoom = joinedRoom, liveLocationStore = locationStore) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val durationState = awaitItem() + + assertThat(durationState.dialogState).isInstanceOf(ShareLocationState.Dialog.LiveLocationDurations::class.java) + } + } + + @Test + fun `ShowLiveLocationDurationPicker uses the active session disclaimer state`() = runTest { + val joinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(sessionId = SessionId("@alice:server"))) + createLiveLocationStore(sessionId = SessionId("@bob:server")) + .setAcceptedLiveLocationDisclaimer() + .getOrThrow() + val presenter = createShareLocationPresenter( + joinedRoom = joinedRoom, + liveLocationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId), + ) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + presenter.test { + skipItems(1) + val state = awaitItem() + + state.eventSink(ShareLocationEvent.InitiateLiveLocationShare) + val dialogState = awaitItem() + + assertThat(dialogState.dialogState).isEqualTo(ShareLocationState.Dialog.LiveLocationDisclaimer) + } + } + @Test fun `ShowLiveLocationDurationPicker shows constraint dialog when permissions denied`() = runTest { - val shareLocationPresenter = createShareLocationPresenter() + val joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = grantedSendLiveLocationPermissions() + ) + ) + val locationStore = createLiveLocationStore(sessionId = joinedRoom.sessionId).apply { + setAcceptedLiveLocationDisclaimer().getOrThrow() + } + val shareLocationPresenter = createShareLocationPresenter( + joinedRoom = joinedRoom, + liveLocationStore = locationStore, + ) fakePermissionsPresenter.givenState( aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, @@ -332,7 +514,7 @@ class ShareLocationPresenterTest { initialState.eventSink(ShareLocationEvent.DismissDialog) val dismissedState = awaitItem() - dismissedState.eventSink(ShareLocationEvent.ShowLiveLocationDurationPicker) + dismissedState.eventSink(ShareLocationEvent.InitiateLiveLocationShare) val constraintDialogState = awaitItem() assertThat(constraintDialogState.dialogState).isEqualTo( @@ -447,4 +629,101 @@ class ShareLocationPresenterTest { cancelAndIgnoreRemainingEvents() } } + + @Test + fun `StartLiveLocationShare event calls manager startShare`() = runTest { + val startShareLambda = lambdaRecorder { _: RoomId, _: Duration -> Result.success(Unit) } + val manager = FakeActiveLiveLocationShareManager( + startShareLambda = startShareLambda, + ) + val shareLocationPresenter = createShareLocationPresenter(liveLocationShareManager = manager) + fakePermissionsPresenter.givenState( + aPermissionsState( + permissions = PermissionsState.Permissions.AllGranted, + shouldShowRationale = false, + ) + ) + + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration = 1.hours)) + advanceUntilIdle() + assert(startShareLambda).isCalledOnce().with( + value(A_ROOM_ID), + value(1.hours) + ) + cancelAndIgnoreRemainingEvents() + } + } + + @Test + fun `canShareLiveLocation is false when the feature is disabled`() = runTest { + fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, false) + val shareLocationPresenter = createShareLocationPresenter( + timelineMode = Timeline.Mode.Live, + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.canShareLiveLocation).isFalse() + } + } + + @Test + fun `canShareLiveLocation is true when the feature is enabled`() = runTest { + fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + val shareLocationPresenter = createShareLocationPresenter( + timelineMode = Timeline.Mode.Live, + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.canShareLiveLocation).isTrue() + } + } + + @Test + fun `canShareLiveLocation is false in thread timeline`() = runTest { + fakeFeatureFlagService.setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + val shareLocationPresenter = createShareLocationPresenter( + timelineMode = Timeline.Mode.Thread(A_THREAD_ID), + ) + shareLocationPresenter.test { + skipItems(1) + val state = awaitItem() + assertThat(state.canShareLiveLocation).isFalse() + } + } } + +private fun createLiveLocationStore( + sessionId: SessionId = A_SESSION_ID, + preferenceDataStoreFactory: PreferenceDataStoreFactory = FakePreferenceDataStoreFactory(), +): LiveLocationStore { + return LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = sessionId, + ) +} + +private fun createFailingLiveLocationStore(sessionId: SessionId = A_SESSION_ID): LiveLocationStore { + val failingPreferenceDataStoreFactory = object : PreferenceDataStoreFactory { + override fun create(name: String): DataStore = object : DataStore { + override val data: Flow = flowOf(emptyPreferences()) + + override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences { + error("Failed to update preferences") + } + } + } + return createLiveLocationStore( + sessionId = sessionId, + preferenceDataStoreFactory = failingPreferenceDataStoreFactory, + ) +} + +private fun grantedSendLiveLocationPermissions(): FakeRoomPermissions = FakeRoomPermissions( + canSendState = { it is StateEventType.BeaconInfo }, + canSendMessage = { it is MessageEventType.Beacon } +) diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt index 63c19ba913..370ccac8ab 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/share/ShareLocationViewTest.kt @@ -143,6 +143,38 @@ class ShareLocationViewTest { clickOn(CommonStrings.action_cancel) eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) } + + @Test + fun `when disclaimer is displayed user can accept`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setShareLocationView( + aShareLocationState( + dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, + eventSink = eventsRecorder, + canShareLiveLocation = true, + ), + navigateUp = EnsureNeverCalled(), + ) + + clickOn(CommonStrings.action_accept) + eventsRecorder.assertSingle(ShareLocationEvent.AcceptLiveLocationDisclaimer) + } + + @Test + fun `when disclaimer is displayed user can decline`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + setShareLocationView( + aShareLocationState( + dialogState = ShareLocationState.Dialog.LiveLocationDisclaimer, + eventSink = eventsRecorder, + canShareLiveLocation = true, + ), + navigateUp = EnsureNeverCalled(), + ) + + clickOn(CommonStrings.action_decline) + eventsRecorder.assertSingle(ShareLocationEvent.DismissDialog) + } } private fun AndroidComposeUiTest.setShareLocationView( diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt index 91df447e2a..985dcc1f9c 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt @@ -16,6 +16,7 @@ import io.element.android.features.location.api.ShowLocationEntryPoint import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.test.core.aBuildMeta @@ -34,6 +35,7 @@ class DefaultShowLocationEntryPointTest { fun `test node builder`() { val entryPoint = DefaultShowLocationEntryPoint() val parentNode = TestParentNode.create { buildContext, plugins -> + val joinedRoom = FakeJoinedRoom() ShowLocationNode( buildContext = buildContext, plugins = plugins, @@ -45,7 +47,8 @@ class DefaultShowLocationEntryPointTest { buildMeta = aBuildMeta(), dateFormatter = FakeDateFormatter(), stringProvider = FakeStringProvider(), - joinedRoom = FakeJoinedRoom(), + joinedRoom = joinedRoom, + liveLocationShareManager = FakeActiveLiveLocationShareManager(), ) }, analyticsService = FakeAnalyticsService(), diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt index 4042cb4c0c..0b8e04abf8 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt @@ -9,7 +9,7 @@ package io.element.android.features.location.impl.show import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare import org.junit.Test class LiveLocationShareComparatorTest { @@ -55,15 +55,3 @@ class LiveLocationShareComparatorTest { assertThat(sortedShares).containsExactly(newerShare, olderShare).inOrder() } } - -private fun aLiveLocationShare( - userId: UserId, - startTimestamp: Long, -): LiveLocationShare { - return LiveLocationShare( - userId = userId, - lastLocation = null, - startTimestamp = startTimestamp, - endTimestamp = startTimestamp + 1_000L, - ) -} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index f38e8dae60..c1f9f6487e 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -20,14 +20,15 @@ import io.element.android.features.location.impl.common.permissions.FakePermissi import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.libraries.dateformatter.test.FakeDateFormatter import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.location.AssetType -import io.element.android.libraries.matrix.api.room.location.LastLocation import io.element.android.libraries.matrix.api.room.location.LiveLocationShare import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test @@ -60,6 +61,7 @@ class ShowLocationPresenterTest { ), locationActions: FakeLocationActions = fakeLocationActions, joinedRoom: JoinedRoom = FakeJoinedRoom(), + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ) = ShowLocationPresenter( mode = mode, permissionsPresenterFactory = { fakePermissionsPresenter }, @@ -68,6 +70,7 @@ class ShowLocationPresenterTest { dateFormatter = fakeDateFormatter, stringProvider = FakeStringProvider(), joinedRoom = joinedRoom, + liveLocationShareManager = liveLocationShareManager, ) @Test @@ -205,7 +208,7 @@ class ShowLocationPresenterTest { ) ) val presenter = createShowLocationPresenter() - presenter.test { + presenter.test { // Skip initial state val initialState = awaitItem() @@ -464,23 +467,3 @@ class ShowLocationPresenterTest { } } } - -private fun aLiveLocationShare( - userId: UserId, - geoUri: String = "geo:48.8584,2.2945", - timestamp: Long = 0L, - startTimestamp: Long = 0L, - endTimestamp: Long = Long.MAX_VALUE, - assetType: AssetType = AssetType.SENDER, -): LiveLocationShare { - return LiveLocationShare( - userId = userId, - lastLocation = LastLocation( - geoUri = geoUri, - timestamp = timestamp, - assetType = assetType, - ), - startTimestamp = startTimestamp, - endTimestamp = endTimestamp, - ) -} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt new file mode 100644 index 0000000000..c42469e705 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/store/LiveLocationStoreTest.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.store + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.mutablePreferencesOf +import androidx.datastore.preferences.core.stringPreferencesKey +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.live.LiveLocationStore +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runTest +import org.junit.Test +import kotlin.time.Instant + +class LiveLocationStoreTest { + private val preferenceDataStoreFactory = FakePreferenceDataStoreFactory() + + @Test + fun `disclaimer defaults to false`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + assertThat(store.hasAcceptedLiveLocationDisclaimer()).isFalse() + } + + @Test + fun `disclaimer acceptance is isolated per session`() = runTest { + val firstStore = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + val secondStore = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = SessionId("@other:server"), + ) + + firstStore.setAcceptedLiveLocationDisclaimer().getOrThrow() + + assertThat(firstStore.hasAcceptedLiveLocationDisclaimer()).isTrue() + assertThat(secondStore.hasAcceptedLiveLocationDisclaimer()).isFalse() + } + + @Test + fun `can persist and read expiry per room`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)).getOrThrow() + + assertThat(store.getLiveLocationExpiries()) + .containsExactly(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)) + } + + @Test + fun `removing one expiry leaves others untouched`() = runTest { + val otherRoomId = RoomId("!other:server") + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)).getOrThrow() + store.setLiveLocationExpiry(otherRoomId, Instant.fromEpochMilliseconds(2_000L)).getOrThrow() + store.removeLiveLocationExpiry(A_ROOM_ID).getOrThrow() + + assertThat(store.getLiveLocationExpiries()) + .containsExactly(otherRoomId, Instant.fromEpochMilliseconds(2_000L)) + } + + @Test + fun `setting expiry twice replaces the existing room value`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = preferenceDataStoreFactory, + sessionId = A_SESSION_ID, + ) + + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(1_000L)).getOrThrow() + store.setLiveLocationExpiry(A_ROOM_ID, Instant.fromEpochMilliseconds(2_000L)).getOrThrow() + + assertThat(store.getLiveLocationExpiries()) + .containsExactly(A_ROOM_ID, Instant.fromEpochMilliseconds(2_000L)) + } + + @Test + fun `malformed expiry payload returns empty map`() = runTest { + val store = LiveLocationStore( + preferenceDataStoreFactory = createMalformedExpiryPreferenceDataStoreFactory(), + sessionId = A_SESSION_ID, + ) + + assertThat(store.getLiveLocationExpiries()).isEmpty() + } + + private fun createMalformedExpiryPreferenceDataStoreFactory(): PreferenceDataStoreFactory { + return object : PreferenceDataStoreFactory { + override fun create(name: String): DataStore { + var preferences: Preferences = mutablePreferencesOf( + stringPreferencesKey("live_location_expiries") to "not valid" + ) + return object : DataStore { + override val data: Flow + get() = flowOf(preferences) + + override suspend fun updateData(transform: suspend (t: Preferences) -> Preferences): Preferences { + preferences = transform(preferences) + return preferences + } + } + } + } + } +} diff --git a/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt new file mode 100644 index 0000000000..255c181ac1 --- /dev/null +++ b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeActiveLiveLocationShareManager.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.test + +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.simulateLongTask +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlin.time.Duration + +class FakeActiveLiveLocationShareManager( + val setupLambda: () -> Unit = { lambdaError() }, + val startShareLambda: (roomId: RoomId, duration: Duration) -> Result = { _, _ -> lambdaError() }, + val stopShareLambda: (roomId: RoomId) -> Result = { _ -> lambdaError() }, +) : ActiveLiveLocationShareManager { + private val _sharingRoomIds = MutableStateFlow(emptySet()) + override val sharingRoomIds: StateFlow> = _sharingRoomIds + + override suspend fun setup() { + setupLambda() + } + + override suspend fun startShare(roomId: RoomId, duration: Duration): Result = simulateLongTask { + startShareLambda(roomId, duration).onSuccess { + _sharingRoomIds.update { + it + roomId + } + } + } + + override suspend fun stopShare(roomId: RoomId): Result = simulateLongTask { + stopShareLambda(roomId).onSuccess { + _sharingRoomIds.update { + it - roomId + } + } + } +} diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt index a96c713ff2..d18d9b73b7 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/biometric/BiometricAuthenticator.kt @@ -36,13 +36,13 @@ interface BiometricAuthenticator { } val isActive: Boolean - fun setup() + suspend fun setup() suspend fun authenticate(): AuthenticationResult } class NoopBiometricAuthentication : BiometricAuthenticator { override val isActive: Boolean = false - override fun setup() = Unit + override suspend fun setup() = Unit override suspend fun authenticate() = BiometricAuthenticator.AuthenticationResult.Failure() } @@ -58,7 +58,7 @@ class DefaultBiometricAuthentication( private var cryptoObject: CryptoObject? = null - override fun setup() { + override suspend fun setup() { try { val secretKey = ensureKey() val cipher = encryptionDecryptionService.createEncryptionCipher(secretKey) @@ -86,7 +86,7 @@ class DefaultBiometricAuthentication( } @Throws(KeyPermanentlyInvalidatedException::class) - private fun ensureKey() = secretKeyRepository.getOrCreateKey(keyAlias, true).also { + private suspend fun ensureKey() = secretKeyRepository.getOrCreateKey(keyAlias, true).also { encryptionDecryptionService.createEncryptionCipher(it) } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt index 091432044a..d699357933 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt @@ -16,9 +16,13 @@ import io.element.android.libraries.cryptography.api.EncryptionDecryptionService import io.element.android.libraries.cryptography.api.EncryptionResult import io.element.android.libraries.cryptography.api.SecretKeyRepository import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import java.util.concurrent.CopyOnWriteArrayList -private const val SECRET_KEY_ALIAS = "elementx.SECRET_KEY_ALIAS_PIN_CODE" +internal const val SECRET_KEY_ALIAS = "elementx.SECRET_KEY_ALIAS_PIN_CODE" @ContributesBinding(AppScope::class) @SingleIn(AppScope::class) @@ -29,6 +33,8 @@ class DefaultPinCodeManager( ) : PinCodeManager { private val callbacks = CopyOnWriteArrayList() + private val migrationMutex = Mutex() + override fun addCallback(callback: PinCodeManager.Callback) { callbacks.add(callback) } @@ -38,11 +44,20 @@ class DefaultPinCodeManager( } override fun hasPinCode(): Flow { - return lockScreenStore.hasPinCode() + return secretKeyRepository.hasKey(SECRET_KEY_ALIAS) + .onStart { + migrationMutex.withLock { + val hasKey = secretKeyRepository.hasKey(SECRET_KEY_ALIAS).first() + if (hasKey && lockScreenStore.getEncryptedCode() == null) { + // Remove the key if there is no pin code + secretKeyRepository.deleteKey(SECRET_KEY_ALIAS) + } + } + } } - override suspend fun getPinCodeSize(): Int { - val encryptedPinCode = lockScreenStore.getEncryptedCode() ?: return 0 + override suspend fun getPinCodeSize(): Int? { + val encryptedPinCode = lockScreenStore.getEncryptedCode() ?: return null val secretKey = secretKeyRepository.getOrCreateKey(SECRET_KEY_ALIAS, false) val decryptedPinCode = encryptionDecryptionService.decrypt(secretKey, EncryptionResult.fromBase64(encryptedPinCode)) return decryptedPinCode.size @@ -79,6 +94,7 @@ class DefaultPinCodeManager( override suspend fun deletePinCode() { lockScreenStore.deleteEncryptedPinCode() lockScreenStore.resetCounter() + secretKeyRepository.deleteKey(SECRET_KEY_ALIAS) callbacks.forEach { it.onPinCodeRemoved() } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt index 9282f3e7df..350631a233 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/PinCodeManager.kt @@ -51,9 +51,9 @@ interface PinCodeManager { fun hasPinCode(): Flow /** - * @return the size of the saved pin code. + * @return the size of the saved pin code. Return null if no pin code is saved. */ - suspend fun getPinCodeSize(): Int + suspend fun getPinCodeSize(): Int? /** * Creates a new encrypted pin code. diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvent.kt similarity index 62% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvent.kt index 2d62427e02..c7437912eb 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsEvent.kt @@ -8,9 +8,9 @@ package io.element.android.features.lockscreen.impl.settings -sealed interface LockScreenSettingsEvents { - data object OnRemovePin : LockScreenSettingsEvents - data object ConfirmRemovePin : LockScreenSettingsEvents - data object CancelRemovePin : LockScreenSettingsEvents - data object ToggleBiometricAllowed : LockScreenSettingsEvents +sealed interface LockScreenSettingsEvent { + data object OnRemovePin : LockScreenSettingsEvent + data object ConfirmRemovePin : LockScreenSettingsEvent + data object CancelRemovePin : LockScreenSettingsEvent + data object ToggleBiometricAllowed : LockScreenSettingsEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt index 589794bde0..83a0253f39 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenter.kt @@ -51,10 +51,10 @@ class LockScreenSettingsPresenter( val biometricUnlock = biometricAuthenticatorManager.rememberConfirmBiometricAuthenticator() - fun handleEvent(event: LockScreenSettingsEvents) { + fun handleEvent(event: LockScreenSettingsEvent) { when (event) { - LockScreenSettingsEvents.CancelRemovePin -> showRemovePinConfirmation = false - LockScreenSettingsEvents.ConfirmRemovePin -> { + LockScreenSettingsEvent.CancelRemovePin -> showRemovePinConfirmation = false + LockScreenSettingsEvent.ConfirmRemovePin -> { coroutineScope.launch { if (showRemovePinConfirmation) { showRemovePinConfirmation = false @@ -62,8 +62,8 @@ class LockScreenSettingsPresenter( } } } - LockScreenSettingsEvents.OnRemovePin -> showRemovePinConfirmation = true - LockScreenSettingsEvents.ToggleBiometricAllowed -> { + LockScreenSettingsEvent.OnRemovePin -> showRemovePinConfirmation = true + LockScreenSettingsEvent.ToggleBiometricAllowed -> { coroutineScope.launch { if (!isBiometricEnabled) { biometricUnlock.setup() diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt index a69d633508..62b8d6d4ee 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsState.kt @@ -13,5 +13,5 @@ data class LockScreenSettingsState( val isBiometricEnabled: Boolean, val showRemovePinConfirmation: Boolean, val showToggleBiometric: Boolean, - val eventSink: (LockScreenSettingsEvents) -> Unit + val eventSink: (LockScreenSettingsEvent) -> Unit ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt index fe5f20da0d..e78a5ee002 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt @@ -51,7 +51,7 @@ fun LockScreenSettingsView( }, style = ListItemStyle.Destructive, onClick = { - state.eventSink(LockScreenSettingsEvents.OnRemovePin) + state.eventSink(LockScreenSettingsEvent.OnRemovePin) } ) } @@ -61,7 +61,7 @@ fun LockScreenSettingsView( title = stringResource(id = R.string.screen_app_lock_settings_enable_biometric_unlock), isChecked = state.isBiometricEnabled, onCheckedChange = { - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } ) } @@ -72,10 +72,10 @@ fun LockScreenSettingsView( title = stringResource(id = R.string.screen_app_lock_settings_remove_pin_alert_title), content = stringResource(id = R.string.screen_app_lock_settings_remove_pin_alert_message), onSubmitClick = { - state.eventSink(LockScreenSettingsEvents.ConfirmRemovePin) + state.eventSink(LockScreenSettingsEvent.ConfirmRemovePin) }, onDismiss = { - state.eventSink(LockScreenSettingsEvents.CancelRemovePin) + state.eventSink(LockScreenSettingsEvent.CancelRemovePin) } ) } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvent.kt similarity index 68% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvent.kt index ab8b18642e..d4db46b731 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricEvent.kt @@ -8,7 +8,7 @@ package io.element.android.features.lockscreen.impl.setup.biometric -sealed interface SetupBiometricEvents { - data object AllowBiometric : SetupBiometricEvents - data object UsePin : SetupBiometricEvents +sealed interface SetupBiometricEvent { + data object AllowBiometric : SetupBiometricEvent + data object UsePin : SetupBiometricEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt index 3af2a28851..ce914320bc 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenter.kt @@ -35,16 +35,16 @@ class SetupBiometricPresenter( val coroutineScope = rememberCoroutineScope() val biometricUnlock = biometricAuthenticatorManager.rememberConfirmBiometricAuthenticator() - fun handleEvent(event: SetupBiometricEvents) { + fun handleEvent(event: SetupBiometricEvent) { when (event) { - SetupBiometricEvents.AllowBiometric -> coroutineScope.launch { + SetupBiometricEvent.AllowBiometric -> coroutineScope.launch { biometricUnlock.setup() if (biometricUnlock.authenticate() == BiometricAuthenticator.AuthenticationResult.Success) { lockScreenStore.setIsBiometricUnlockAllowed(true) isBiometricSetupDone = true } } - SetupBiometricEvents.UsePin -> coroutineScope.launch { + SetupBiometricEvent.UsePin -> coroutineScope.launch { lockScreenStore.setIsBiometricUnlockAllowed(false) isBiometricSetupDone = true } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt index 2843c028d1..db11b1dc30 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricState.kt @@ -10,5 +10,5 @@ package io.element.android.features.lockscreen.impl.setup.biometric data class SetupBiometricState( val isBiometricSetupDone: Boolean, - val eventSink: (SetupBiometricEvents) -> Unit + val eventSink: (SetupBiometricEvent) -> Unit ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt index 35b1ec76c0..70a1046e36 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricView.kt @@ -33,7 +33,7 @@ fun SetupBiometricView( modifier: Modifier = Modifier, ) { BackHandler { - state.eventSink(SetupBiometricEvents.UsePin) + state.eventSink(SetupBiometricEvent.UsePin) } HeaderFooterPage( modifier = modifier.padding(top = 80.dp), @@ -42,8 +42,8 @@ fun SetupBiometricView( }, footer = { SetupBiometricFooter( - onAllowClick = { state.eventSink(SetupBiometricEvents.AllowBiometric) }, - onSkipClick = { state.eventSink(SetupBiometricEvents.UsePin) } + onAllowClick = { state.eventSink(SetupBiometricEvent.AllowBiometric) }, + onSkipClick = { state.eventSink(SetupBiometricEvent.UsePin) } ) }, ) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvent.kt similarity index 74% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvent.kt index 276a94b2fc..f0dfdc33f0 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinEvent.kt @@ -8,7 +8,7 @@ package io.element.android.features.lockscreen.impl.setup.pin -sealed interface SetupPinEvents { - data class OnPinEntryChanged(val entryAsText: String, val fromConfirmationStep: Boolean) : SetupPinEvents - data object ClearFailure : SetupPinEvents +sealed interface SetupPinEvent { + data class OnPinEntryChanged(val entryAsText: String, val fromConfirmationStep: Boolean) : SetupPinEvent + data object ClearFailure : SetupPinEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt index ac5b5bd1cc..d780927d44 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenter.kt @@ -74,9 +74,9 @@ class SetupPinPresenter( } } - fun handleEvent(event: SetupPinEvents) { + fun handleEvent(event: SetupPinEvent) { when (event) { - is SetupPinEvents.OnPinEntryChanged -> { + is SetupPinEvent.OnPinEntryChanged -> { // Use the fromConfirmationStep flag from ui to avoid race condition. if (event.fromConfirmationStep) { confirmPinEntry = confirmPinEntry.fillWith(event.entryAsText) @@ -84,7 +84,7 @@ class SetupPinPresenter( choosePinEntry = choosePinEntry.fillWith(event.entryAsText) } } - SetupPinEvents.ClearFailure -> { + SetupPinEvent.ClearFailure -> { when (setupPinFailure) { is SetupPinFailure.PinsDoNotMatch -> { choosePinEntry = choosePinEntry.clear() diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt index 2d5124d440..cf65e63c1b 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinState.kt @@ -17,7 +17,7 @@ data class SetupPinState( val isConfirmationStep: Boolean, val setupPinFailure: SetupPinFailure?, val appName: String, - val eventSink: (SetupPinEvents) -> Unit + val eventSink: (SetupPinEvent) -> Unit ) { val activePinEntry = if (isConfirmationStep) { confirmPinEntry diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt index 5f2320db32..508d3c1fbb 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinView.kt @@ -107,7 +107,7 @@ private fun SetupPinContent( pinEntry = state.activePinEntry, isSecured = true, onValueChange = { entry -> - state.eventSink(SetupPinEvents.OnPinEntryChanged(entry, state.isConfirmationStep)) + state.eventSink(SetupPinEvent.OnPinEntryChanged(entry, state.isConfirmationStep)) }, modifier = Modifier .focusRequester(focusRequester) @@ -119,7 +119,7 @@ private fun SetupPinContent( title = state.setupPinFailure.title(), content = state.setupPinFailure.content(), onSubmit = { - state.eventSink(SetupPinEvents.ClearFailure) + state.eventSink(SetupPinEvent.ClearFailure) } ) } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt index c4558812de..b41e6a9578 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/EncryptedPinCodeStorage.kt @@ -8,8 +8,6 @@ package io.element.android.features.lockscreen.impl.storage -import kotlinx.coroutines.flow.Flow - /** * Should be implemented by any class that provides access to the encrypted PIN code. * All methods are suspending in case there are async IO operations involved. @@ -29,9 +27,4 @@ interface EncryptedPinCodeStorage { * Deletes the PIN code from some persistable storage. */ suspend fun deleteEncryptedPinCode() - - /** - * Returns whether the PIN code is stored or not. - */ - fun hasPinCode(): Flow } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt index 6b99d90592..bce20b2418 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/storage/PreferencesLockScreenStore.kt @@ -70,12 +70,6 @@ class PreferencesLockScreenStore( } } - override fun hasPinCode(): Flow { - return dataStore.data.map { preferences -> - preferences[pinCodeKey] != null - } - } - override fun isBiometricUnlockAllowed(): Flow { return dataStore.data.map { preferences -> preferences[biometricUnlockKey] ?: false @@ -88,5 +82,7 @@ class PreferencesLockScreenStore( } } - private fun Preferences.getRemainingPinCodeAttemptsNumber() = this[remainingAttemptsKey] ?: lockScreenConfig.maxPinCodeAttemptsBeforeLogout + private fun Preferences.getRemainingPinCodeAttemptsNumber() = + this[remainingAttemptsKey]?.coerceIn(0, lockScreenConfig.maxPinCodeAttemptsBeforeLogout) + ?: lockScreenConfig.maxPinCodeAttemptsBeforeLogout } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvents.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvent.kt similarity index 61% rename from features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvents.kt rename to features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvent.kt index bd9043859f..aa96a2e115 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvents.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockEvent.kt @@ -10,12 +10,12 @@ package io.element.android.features.lockscreen.impl.unlock import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel -sealed interface PinUnlockEvents { - data class OnPinKeypadPressed(val pinKeypadModel: PinKeypadModel) : PinUnlockEvents - data class OnPinEntryChanged(val entryAsText: String) : PinUnlockEvents - data object OnForgetPin : PinUnlockEvents - data object ClearSignOutPrompt : PinUnlockEvents - data object SignOut : PinUnlockEvents - data object OnUseBiometric : PinUnlockEvents - data object ClearBiometricError : PinUnlockEvents +sealed interface PinUnlockEvent { + data class OnPinKeypadPressed(val pinKeypadModel: PinKeypadModel) : PinUnlockEvent + data class OnPinEntryChanged(val entryAsText: String) : PinUnlockEvent + data object OnForgetPin : PinUnlockEvent + data object ClearSignOutPrompt : PinUnlockEvent + data object SignOut : PinUnlockEvent + data object OnUseBiometric : PinUnlockEvent + data object ClearBiometricError : PinUnlockEvent } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt index 5429320fc7..c8dd8916f9 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenter.kt @@ -69,7 +69,13 @@ class PinUnlockPresenter( LaunchedEffect(Unit) { suspend { val pinCodeSize = pinCodeManager.getPinCodeSize() - PinEntry.createEmpty(pinCodeSize) + if (pinCodeSize == null) { + // No pin code set, deleted store? Force sign out + showSignOutPrompt = true + error("No pin code size found") + } else { + PinEntry.createEmpty(pinCodeSize) + } }.runCatchingUpdatingState(pinEntryState) } LaunchedEffect(biometricUnlock) { @@ -95,28 +101,28 @@ class PinUnlockPresenter( isUnlocked.value = true } - fun handleEvent(event: PinUnlockEvents) { + fun handleEvent(event: PinUnlockEvent) { when (event) { - is PinUnlockEvents.OnPinKeypadPressed -> { + is PinUnlockEvent.OnPinKeypadPressed -> { pinEntryState.value = pinEntry.process(event.pinKeypadModel) } - PinUnlockEvents.OnForgetPin -> showSignOutPrompt = true - PinUnlockEvents.ClearSignOutPrompt -> showSignOutPrompt = false - PinUnlockEvents.SignOut -> { + PinUnlockEvent.OnForgetPin -> showSignOutPrompt = true + PinUnlockEvent.ClearSignOutPrompt -> showSignOutPrompt = false + PinUnlockEvent.SignOut -> { if (showSignOutPrompt) { showSignOutPrompt = false coroutineScope.signOut(signOutAction) } } - PinUnlockEvents.OnUseBiometric -> { + PinUnlockEvent.OnUseBiometric -> { coroutineScope.launch { biometricUnlockResult = biometricUnlock.authenticate() } } - PinUnlockEvents.ClearBiometricError -> { + PinUnlockEvent.ClearBiometricError -> { biometricUnlockResult = null } - is PinUnlockEvents.OnPinEntryChanged -> { + is PinUnlockEvent.OnPinEntryChanged -> { pinEntryState.value = pinEntry.process(event.entryAsText) } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt index 2bbcbe335c..037aa87dec 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockState.kt @@ -23,11 +23,15 @@ data class PinUnlockState( val showBiometricUnlock: Boolean, val isUnlocked: Boolean, val biometricUnlockResult: BiometricAuthenticator.AuthenticationResult?, - val eventSink: (PinUnlockEvents) -> Unit + val eventSink: (PinUnlockEvent) -> Unit ) { - val isSignOutPromptCancellable = when (remainingAttempts) { - is AsyncData.Success -> remainingAttempts.data > 0 - else -> true + val isSignOutPromptCancellable = if (pinEntry.isFailure()) { + false + } else { + when (remainingAttempts) { + is AsyncData.Success -> remainingAttempts.data > 0 + else -> true + } } val biometricUnlockErrorMessage = when { diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt index 2beb8babe3..1b8166a8ac 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockStateProvider.kt @@ -20,7 +20,7 @@ open class PinUnlockStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aPinUnlockState(), - aPinUnlockState(pinEntry = PinEntry.createEmpty(4).fillWith("12")), + aPinUnlockState(pinEntry = AsyncData.Success(PinEntry.createEmpty(4).fillWith("12"))), aPinUnlockState(showWrongPinTitle = true), aPinUnlockState(showSignOutPrompt = true), aPinUnlockState(showBiometricUnlock = false), @@ -31,11 +31,18 @@ open class PinUnlockStateProvider : PreviewParameterProvider { BiometricUnlockError(BiometricPrompt.ERROR_LOCKOUT, "Biometric auth disabled") ) ), + aPinUnlockState(showSignOutPrompt = true, pinEntry = AsyncData.Failure(Exception("An error occurred"))), + // User enter wrong pin once, and then correct PIN. In this case, the error (with counter reset to 3) should not be displayed. + aPinUnlockState( + remainingAttempts = AsyncData.Success(2), + showWrongPinTitle = true, + isUnlocked = true, + ), ) } fun aPinUnlockState( - pinEntry: PinEntry = PinEntry.createEmpty(4), + pinEntry: AsyncData = AsyncData.Success(PinEntry.createEmpty(4)), remainingAttempts: AsyncData = AsyncData.Success(3), showWrongPinTitle: Boolean = false, showSignOutPrompt: Boolean = false, @@ -44,7 +51,7 @@ fun aPinUnlockState( isUnlocked: Boolean = false, signOutAction: AsyncAction = AsyncAction.Uninitialized, ) = PinUnlockState( - pinEntry = AsyncData.Success(pinEntry), + pinEntry = pinEntry, showWrongPinTitle = showWrongPinTitle, remainingAttempts = remainingAttempts, showSignOutPrompt = showSignOutPrompt, diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt index 659f8c2966..6749697b64 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockView.kt @@ -69,7 +69,7 @@ fun PinUnlockView( ) { OnLifecycleEvent { _, event -> when (event) { - Lifecycle.Event.ON_RESUME -> state.eventSink.invoke(PinUnlockEvents.OnUseBiometric) + Lifecycle.Event.ON_RESUME -> state.eventSink.invoke(PinUnlockEvent.OnUseBiometric) else -> Unit } } @@ -78,8 +78,8 @@ fun PinUnlockView( if (state.showSignOutPrompt) { SignOutPrompt( isCancellable = state.isSignOutPromptCancellable, - onSignOut = { state.eventSink(PinUnlockEvents.SignOut) }, - onDismiss = { state.eventSink(PinUnlockEvents.ClearSignOutPrompt) }, + onSignOut = { state.eventSink(PinUnlockEvent.SignOut) }, + onDismiss = { state.eventSink(PinUnlockEvent.ClearSignOutPrompt) }, ) } when (state.signOutAction) { @@ -95,7 +95,7 @@ fun PinUnlockView( if (state.showBiometricUnlockError) { ErrorDialog( content = state.biometricUnlockErrorMessage ?: "", - onSubmit = { state.eventSink(PinUnlockEvents.ClearBiometricError) } + onSubmit = { state.eventSink(PinUnlockEvent.ClearBiometricError) } ) } } @@ -108,10 +108,10 @@ private fun PinUnlockPage( ) { BoxWithConstraints { val commonModifier = Modifier - .fillMaxSize() - .systemBarsPadding() - .imePadding() - .padding(all = 20.dp) + .fillMaxSize() + .systemBarsPadding() + .imePadding() + .padding(all = 20.dp) val header = @Composable { PinUnlockHeader( @@ -125,10 +125,10 @@ private fun PinUnlockPage( modifier = Modifier.padding(top = 24.dp), showBiometricUnlock = state.showBiometricUnlock, onUseBiometric = { - state.eventSink(PinUnlockEvents.OnUseBiometric) + state.eventSink(PinUnlockEvent.OnUseBiometric) }, onForgotPin = { - state.eventSink(PinUnlockEvents.OnForgetPin) + state.eventSink(PinUnlockEvent.OnForgetPin) }, ) } @@ -144,17 +144,17 @@ private fun PinUnlockPage( pinEntry = pinEntry, isSecured = true, onValueChange = { - state.eventSink(PinUnlockEvents.OnPinEntryChanged(it)) + state.eventSink(PinUnlockEvent.OnPinEntryChanged(it)) }, modifier = Modifier - .focusRequester(focusRequester) - .fillMaxWidth() + .focusRequester(focusRequester) + .fillMaxWidth() ) } } else { PinKeypad( onClick = { - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(it)) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(it)) }, maxWidth = constraints.maxWidth, maxHeight = constraints.maxHeight, @@ -217,8 +217,8 @@ private fun PinUnlockCompactView( } BoxWithConstraints( modifier = Modifier - .weight(1f) - .fillMaxHeight(), + .weight(1f) + .fillMaxHeight(), contentAlignment = Alignment.Center, ) { content() @@ -239,9 +239,9 @@ private fun PinUnlockExpandedView( header() BoxWithConstraints( modifier = Modifier - .weight(1f) - .fillMaxWidth() - .padding(top = 40.dp), + .weight(1f) + .fillMaxWidth() + .padding(top = 40.dp), ) { content() } @@ -274,8 +274,8 @@ private fun PinDot( } Box( modifier = Modifier - .size(14.dp) - .background(backgroundColor, CircleShape) + .size(14.dp) + .background(backgroundColor, CircleShape) ) } @@ -311,14 +311,26 @@ private fun PinUnlockHeader( ) Spacer(Modifier.height(8.dp)) val remainingAttempts = state.remainingAttempts.dataOrNull() - val subtitle = if (remainingAttempts != null) { - if (state.showWrongPinTitle) { - pluralStringResource(id = R.plurals.screen_app_lock_subtitle_wrong_pin, count = remainingAttempts, remainingAttempts) - } else { - pluralStringResource(id = R.plurals.screen_app_lock_subtitle, count = remainingAttempts, remainingAttempts) + val subtitle = when { + state.isUnlocked -> { + // Hide any previous error + "" } - } else { - "" + remainingAttempts != null -> + if (state.showWrongPinTitle) { + pluralStringResource( + id = R.plurals.screen_app_lock_subtitle_wrong_pin, + count = remainingAttempts, + remainingAttempts, + ) + } else { + pluralStringResource( + id = R.plurals.screen_app_lock_subtitle, + count = remainingAttempts, + remainingAttempts, + ) + } + else -> "" } val subtitleColor = if (state.showWrongPinTitle) { ElementTheme.colors.textCriticalPrimary diff --git a/features/lockscreen/impl/src/main/res/values-fa/translations.xml b/features/lockscreen/impl/src/main/res/values-fa/translations.xml index bd2000b94d..0575f22221 100644 --- a/features/lockscreen/impl/src/main/res/values-fa/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-fa/translations.xml @@ -23,7 +23,7 @@ "لطفاً یک پین را دو بار وارد کنید" "پین‌ها مطابق نیستند" "برای ادامه باید دوباره وارد شده و پینی جدید ایجاد کنید" - "دارید خارج می‌شوید" + "این دستگاه در حال حذف شدن است" "شما %1$d تلاش برای باز کردن قفل دارید" "شما %1$d تلاش برای باز کردن قفل دارید" diff --git a/features/lockscreen/impl/src/main/res/values-pl/translations.xml b/features/lockscreen/impl/src/main/res/values-pl/translations.xml index 5d61ecb7c6..29691987f6 100644 --- a/features/lockscreen/impl/src/main/res/values-pl/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-pl/translations.xml @@ -23,7 +23,7 @@ Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz ten PIN, zostaniesz wyl "Wprowadź ten sam kod PIN dwa razy" "PIN\'y nie pasują do siebie" "Aby kontynuować, zaloguj się ponownie i utwórz nowy kod PIN" - "Trwa wylogowywanie" + "Trwa usuwanie urządzenia" "Masz %1$d próbę, żeby odblokować" "Masz %1$d próby, żeby odblokować" @@ -36,5 +36,5 @@ Wybierz coś łatwego do zapamiętania. Jeśli zapomnisz ten PIN, zostaniesz wyl "Użyj biometrii" "Użyj kodu PIN" - "Wylogowywanie…" + "Usuwam urządzenie…" diff --git a/features/lockscreen/impl/src/main/res/values-sk/translations.xml b/features/lockscreen/impl/src/main/res/values-sk/translations.xml index 0cfb2e88cd..14687f9272 100644 --- a/features/lockscreen/impl/src/main/res/values-sk/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-sk/translations.xml @@ -36,5 +36,5 @@ Vyberte si niečo zapamätateľné. Ak tento kód PIN zabudnete, budete z aplik "Použiť biometrické údaje" "Použiť PIN" - "Prebieha odhlasovanie…" + "Odoberanie zariadenia…" diff --git a/features/lockscreen/impl/src/main/res/values-uk/translations.xml b/features/lockscreen/impl/src/main/res/values-uk/translations.xml index 5c19889282..25e96003c8 100644 --- a/features/lockscreen/impl/src/main/res/values-uk/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-uk/translations.xml @@ -36,5 +36,5 @@ "Використати біометрію" "Використати PIN-код" - "Вихід…" + "Видалення пристрою…" diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt index 9082f20a55..f906d0d6ba 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenServiceTest.kt @@ -14,9 +14,12 @@ import io.element.android.features.lockscreen.impl.biometric.BiometricAuthentica import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthenticatorManager import io.element.android.features.lockscreen.impl.fixtures.aLockScreenConfig import io.element.android.features.lockscreen.impl.pin.PinCodeManager +import io.element.android.features.lockscreen.impl.pin.SECRET_KEY_ALIAS import io.element.android.features.lockscreen.impl.pin.createDefaultPinCodeManager import io.element.android.features.lockscreen.impl.pin.storage.InMemoryLockScreenStore import io.element.android.features.lockscreen.impl.storage.LockScreenStore +import io.element.android.libraries.cryptography.api.SecretKeyRepository +import io.element.android.libraries.cryptography.test.SimpleSecretKeyRepository import io.element.android.libraries.sessionstorage.api.observer.SessionObserver import io.element.android.libraries.sessionstorage.test.observer.FakeSessionObserver import io.element.android.services.appnavstate.api.AppForegroundStateService @@ -38,18 +41,18 @@ class DefaultLockScreenServiceTest { @Test fun `when the pin is mandatory, isSetupRequired emits true`() = runTest { - val lockScreenStore = InMemoryLockScreenStore() + val secretKeyRepository = SimpleSecretKeyRepository() val sut = createDefaultLockScreenService( lockScreenConfig = aLockScreenConfig(isPinMandatory = true), - lockScreenStore = lockScreenStore, + secretKeyRepository = secretKeyRepository, ) sut.isSetupRequired().test { assertThat(awaitItem()).isTrue() // When the user configures the pin code, the setup is not required anymore - lockScreenStore.saveEncryptedPinCode("encryptedCode") + secretKeyRepository.getOrCreateKey(SECRET_KEY_ALIAS, true) assertThat(awaitItem()).isFalse() // Users deletes the pin code - lockScreenStore.deleteEncryptedPinCode() + secretKeyRepository.deleteKey("elementx.SECRET_KEY_ALIAS_PIN_CODE") assertThat(awaitItem()).isTrue() } } @@ -57,16 +60,16 @@ class DefaultLockScreenServiceTest { @Test fun `when the last session is deleted, the pin code is removed`() = runTest { val sessionObserver = FakeSessionObserver() - val lockScreenStore = InMemoryLockScreenStore() + val secretKeyRepository = SimpleSecretKeyRepository() val sut = createDefaultLockScreenService( lockScreenConfig = aLockScreenConfig(isPinMandatory = true), - lockScreenStore = lockScreenStore, + secretKeyRepository = secretKeyRepository, sessionObserver = sessionObserver, ) sut.isPinSetup().test { assertThat(awaitItem()).isFalse() // When the user configure the pin code, the setup is not required anymore - lockScreenStore.saveEncryptedPinCode("encryptedCode") + secretKeyRepository.getOrCreateKey(SECRET_KEY_ALIAS, true) assertThat(awaitItem()).isTrue() sessionObserver.onSessionDeleted("userId", wasLastSession = false) expectNoEvents() @@ -79,8 +82,10 @@ class DefaultLockScreenServiceTest { private fun TestScope.createDefaultLockScreenService( lockScreenConfig: LockScreenConfig = aLockScreenConfig(), lockScreenStore: LockScreenStore = InMemoryLockScreenStore(), + secretKeyRepository: SecretKeyRepository = SimpleSecretKeyRepository(), pinCodeManager: PinCodeManager = createDefaultPinCodeManager( lockScreenStore = lockScreenStore, + secretKeyRepository = secretKeyRepository, ), sessionObserver: SessionObserver = FakeSessionObserver(), appForegroundStateService: AppForegroundStateService = FakeAppForegroundStateService(), diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt index 073bdc799d..63729f941a 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/biometric/FakeBiometricAuthenticator.kt @@ -12,6 +12,6 @@ class FakeBiometricAuthenticator( override val isActive: Boolean = false, private val authenticateLambda: suspend () -> BiometricAuthenticator.AuthenticationResult = { BiometricAuthenticator.AuthenticationResult.Success }, ) : BiometricAuthenticator { - override fun setup() = Unit + override suspend fun setup() = Unit override suspend fun authenticate() = authenticateLambda() } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt index 61acf71cdd..312a33b7f1 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryLockScreenStore.kt @@ -15,12 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow private const val DEFAULT_REMAINING_ATTEMPTS = 3 class InMemoryLockScreenStore : LockScreenStore { - private val hasPinCode = MutableStateFlow(false) private var pinCode: String? = null - set(value) { - field = value - hasPinCode.value = value != null - } private var remainingAttempts: Int = DEFAULT_REMAINING_ATTEMPTS private var isBiometricUnlockAllowed = MutableStateFlow(false) @@ -48,10 +43,6 @@ class InMemoryLockScreenStore : LockScreenStore { pinCode = null } - override fun hasPinCode(): Flow { - return hasPinCode - } - override fun isBiometricUnlockAllowed(): Flow { return isBiometricUnlockAllowed } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt index ef3e94f27f..85eb4a37e7 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsPresenterTest.kt @@ -43,19 +43,19 @@ class LockScreenSettingsPresenterTest { consumeItemsUntilPredicate { state -> state.showRemovePinOption }.last().also { state -> - state.eventSink(LockScreenSettingsEvents.OnRemovePin) + state.eventSink(LockScreenSettingsEvent.OnRemovePin) } awaitLastSequentialItem().also { state -> assertThat(state.showRemovePinConfirmation).isTrue() - state.eventSink(LockScreenSettingsEvents.CancelRemovePin) + state.eventSink(LockScreenSettingsEvent.CancelRemovePin) } awaitLastSequentialItem().also { state -> assertThat(state.showRemovePinConfirmation).isFalse() - state.eventSink(LockScreenSettingsEvents.OnRemovePin) + state.eventSink(LockScreenSettingsEvent.OnRemovePin) } awaitLastSequentialItem().also { state -> assertThat(state.showRemovePinConfirmation).isTrue() - state.eventSink(LockScreenSettingsEvents.ConfirmRemovePin) + state.eventSink(LockScreenSettingsEvent.ConfirmRemovePin) } consumeItemsUntilPredicate { it.showRemovePinOption.not() @@ -93,7 +93,7 @@ class LockScreenSettingsPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } awaitItem().also { state -> assertThat(state.isBiometricEnabled).isTrue() @@ -114,7 +114,7 @@ class LockScreenSettingsPresenterTest { presenter.test { skipItems(1) awaitItem().also { state -> - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } } } @@ -137,7 +137,7 @@ class LockScreenSettingsPresenterTest { skipItems(1) awaitItem().also { state -> assertThat(state.isBiometricEnabled).isTrue() - state.eventSink(LockScreenSettingsEvents.ToggleBiometricAllowed) + state.eventSink(LockScreenSettingsEvent.ToggleBiometricAllowed) } awaitItem().also { state -> assertThat(state.isBiometricEnabled).isFalse() diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt index 3f87c1dccf..9dde220906 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/biometric/SetupBiometricPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.lockscreen.impl.setup.biometric -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticator import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticatorManager @@ -18,6 +15,7 @@ import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthen import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthenticatorManager import io.element.android.features.lockscreen.impl.pin.storage.InMemoryLockScreenStore import io.element.android.features.lockscreen.impl.storage.LockScreenStore +import io.element.android.tests.testutils.test import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.junit.Test @@ -30,12 +28,10 @@ class SetupBiometricPresenterTest { FakeBiometricAuthenticator(authenticateLambda = { BiometricAuthenticator.AuthenticationResult.Success }) }) val presenter = createSetupBiometricPresenter(lockScreenStore, fakeBiometricAuthenticatorManager) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() - state.eventSink(SetupBiometricEvents.AllowBiometric) + state.eventSink(SetupBiometricEvent.AllowBiometric) } awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isTrue() @@ -51,12 +47,10 @@ class SetupBiometricPresenterTest { FakeBiometricAuthenticator(authenticateLambda = { BiometricAuthenticator.AuthenticationResult.Failure() }) }) val presenter = createSetupBiometricPresenter(lockScreenStore, fakeBiometricAuthenticatorManager) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() - state.eventSink(SetupBiometricEvents.AllowBiometric) + state.eventSink(SetupBiometricEvent.AllowBiometric) } } assertThat(lockScreenStore.isBiometricUnlockAllowed().first()).isFalse() @@ -66,12 +60,10 @@ class SetupBiometricPresenterTest { fun `present - skip flow`() = runTest { val lockScreenStore = InMemoryLockScreenStore() val presenter = createSetupBiometricPresenter(lockScreenStore) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isFalse() - state.eventSink(SetupBiometricEvents.UsePin) + state.eventSink(SetupBiometricEvent.UsePin) } awaitItem().also { state -> assertThat(state.isBiometricSetupDone).isTrue() diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt index 6a1d32e879..9d63f9e26b 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/setup/pin/SetupPinPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.lockscreen.impl.setup.pin -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.impl.LockScreenConfig import io.element.android.features.lockscreen.impl.fixtures.aLockScreenConfig @@ -24,6 +21,7 @@ import io.element.android.features.lockscreen.impl.setup.pin.validation.SetupPin import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.tests.testutils.awaitLastSequentialItem import io.element.android.tests.testutils.consumeItemsUntilPredicate +import io.element.android.tests.testutils.test import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.test.runTest import org.junit.Test @@ -43,9 +41,7 @@ class SetupPinPresenterTest { } } val presenter = createSetupPinPresenter(callback) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> state.choosePinEntry.assertEmpty() state.confirmPinEntry.assertEmpty() @@ -63,7 +59,7 @@ class SetupPinPresenterTest { awaitLastSequentialItem().also { state -> state.choosePinEntry.assertText(forbiddenPin) assertThat(state.setupPinFailure).isEqualTo(SetupPinFailure.ForbiddenPin) - state.eventSink(SetupPinEvents.ClearFailure) + state.eventSink(SetupPinEvent.ClearFailure) } awaitLastSequentialItem().also { state -> state.choosePinEntry.assertEmpty() @@ -82,7 +78,7 @@ class SetupPinPresenterTest { state.choosePinEntry.assertText(completePin) state.confirmPinEntry.assertText(mismatchedPin) assertThat(state.setupPinFailure).isEqualTo(SetupPinFailure.PinsDoNotMatch) - state.eventSink(SetupPinEvents.ClearFailure) + state.eventSink(SetupPinEvent.ClearFailure) } awaitLastSequentialItem().also { state -> state.choosePinEntry.assertEmpty() @@ -108,7 +104,7 @@ class SetupPinPresenterTest { } private fun SetupPinState.onPinEntryChanged(pinEntry: String) { - eventSink(SetupPinEvents.OnPinEntryChanged(pinEntry, isConfirmationStep)) + eventSink(SetupPinEvent.OnPinEntryChanged(pinEntry, isConfirmationStep)) } private fun createSetupPinPresenter( diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt index f5bfb11818..fa7d05b5cb 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt @@ -8,9 +8,6 @@ package io.element.android.features.lockscreen.impl.unlock -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.features.lockscreen.impl.biometric.BiometricAuthenticatorManager import io.element.android.features.lockscreen.impl.biometric.FakeBiometricAuthenticatorManager @@ -19,12 +16,14 @@ import io.element.android.features.lockscreen.impl.pin.DefaultPinCodeManagerCall import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.features.lockscreen.impl.pin.model.assertText +import io.element.android.features.lockscreen.impl.pin.storage.InMemoryLockScreenStore import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel import io.element.android.features.logout.test.FakeLogoutUseCase import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.AsyncData import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -36,9 +35,7 @@ class PinUnlockPresenterTest { @Test fun `present - success verify flow`() = runTest { val presenter = createPinUnlockPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Uninitialized::class.java) assertThat(state.showWrongPinTitle).isFalse() @@ -50,17 +47,17 @@ class PinUnlockPresenterTest { awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) assertThat(state.remainingAttempts).isInstanceOf(AsyncData.Success::class.java) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('1'))) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('2'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('1'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('2'))) } skipItems(1) awaitItem().also { state -> state.pinEntry.assertText(halfCompletePin) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('3'))) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Back)) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Empty)) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('3'))) - state.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('5'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('3'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Back)) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Empty)) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('3'))) + state.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('5'))) } skipItems(4) awaitItem().also { state -> @@ -73,9 +70,7 @@ class PinUnlockPresenterTest { @Test fun `present - failure verify flow`() = runTest { val presenter = createPinUnlockPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) val initialState = awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) @@ -83,10 +78,10 @@ class PinUnlockPresenterTest { } val numberOfAttempts = initialState.remainingAttempts.dataOrNull() ?: 0 repeat(numberOfAttempts) { - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('1'))) - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('2'))) - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('3'))) - initialState.eventSink(PinUnlockEvents.OnPinKeypadPressed(PinKeypadModel.Number('4'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('1'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('2'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('3'))) + initialState.eventSink(PinUnlockEvent.OnPinKeypadPressed(PinKeypadModel.Number('4'))) } skipItems(4 * numberOfAttempts + 2) awaitItem().also { state -> @@ -102,27 +97,25 @@ class PinUnlockPresenterTest { val signOutLambda = lambdaRecorder {} val signOut = FakeLogoutUseCase(signOutLambda) val presenter = createPinUnlockPresenter(logoutUseCase = signOut) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { skipItems(1) awaitItem().also { state -> assertThat(state.pinEntry).isInstanceOf(AsyncData.Success::class.java) assertThat(state.remainingAttempts).isInstanceOf(AsyncData.Success::class.java) - state.eventSink(PinUnlockEvents.OnForgetPin) + state.eventSink(PinUnlockEvent.OnForgetPin) } awaitItem().also { state -> assertThat(state.showSignOutPrompt).isTrue() assertThat(state.isSignOutPromptCancellable).isTrue() - state.eventSink(PinUnlockEvents.ClearSignOutPrompt) + state.eventSink(PinUnlockEvent.ClearSignOutPrompt) } awaitItem().also { state -> assertThat(state.showSignOutPrompt).isFalse() - state.eventSink(PinUnlockEvents.OnForgetPin) + state.eventSink(PinUnlockEvent.OnForgetPin) } awaitItem().also { state -> assertThat(state.showSignOutPrompt).isTrue() - state.eventSink(PinUnlockEvents.SignOut) + state.eventSink(PinUnlockEvent.SignOut) } skipItems(2) awaitItem().also { state -> @@ -132,6 +125,28 @@ class PinUnlockPresenterTest { } } + @Test + fun `present - pin is configured, but deleted in store, sign out prompt will be shown`() = runTest { + val lockScreenStore = InMemoryLockScreenStore() + val pinCodeManager = aPinCodeManager( + lockScreenStore = lockScreenStore, + ) + val presenter = createPinUnlockPresenter( + pinCodeManager = pinCodeManager, + ) + // Delete the pin code from the store + lockScreenStore.deleteEncryptedPinCode() + presenter.test { + skipItems(1) + awaitItem().also { state -> + assertThat(state.pinEntry).isInstanceOf(AsyncData.Failure::class.java) + assertThat(state.showSignOutPrompt).isTrue() + assertThat(state.isSignOutPromptCancellable).isFalse() + assertThat(state.remainingAttempts.dataOrNull()).isEqualTo(3) + } + } + } + private fun AsyncData.assertText(text: String) { dataOrNull()?.assertText(text) } @@ -139,9 +154,10 @@ class PinUnlockPresenterTest { private suspend fun TestScope.createPinUnlockPresenter( biometricAuthenticatorManager: BiometricAuthenticatorManager = FakeBiometricAuthenticatorManager(), callback: PinCodeManager.Callback = DefaultPinCodeManagerCallback(), - logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase(logoutLambda = { "" }), + logoutUseCase: FakeLogoutUseCase = FakeLogoutUseCase(logoutLambda = {}), + pinCodeManager: PinCodeManager = aPinCodeManager() ): PinUnlockPresenter { - val pinCodeManager = aPinCodeManager().apply { + pinCodeManager.apply { addCallback(callback) createPinCode(completePin) } diff --git a/features/login/impl/src/main/res/values-el/translations.xml b/features/login/impl/src/main/res/values-el/translations.xml index 85640698f3..045465902b 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -28,7 +28,7 @@ "Ποια είναι η διεύθυνση του διακομιστή σου;" "Επέλεξε το διακομιστή σου" "Δημιουργία λογαριασμού" - "Αυτός ο λογαριασμός έχει απενεργοποιηθεί." + "Αυτός ο λογαριασμός έχει διαγραφεί." "Λανθασμένο όνομα χρήστη ή κωδικός πρόσβασης" "Αυτό δεν είναι έγκυρο αναγνωριστικό χρήστη. Αναμενόμενη μορφή: \'@χρήστης:homeserver.org\'" "Αυτός ο διακομιστής έχει ρυθμιστεί ώστε να χρησιμοποιεί διακριτικά ανανέωσης. Αυτά δεν υποστηρίζονται όταν χρησιμοποιείς σύνδεση μέσω κωδικού πρόσβασης." @@ -37,6 +37,13 @@ "Το Matrix είναι ένα ανοιχτό δίκτυο για ασφαλή, αποκεντρωμένη επικοινωνία." "Καλωσόρισες ξανά!" "Συνδέσου στο %1$s" + "Άνοιγμα του Element Classic" + "Ανοίξτε το Element Classic στη συσκευή σας." + "Μεταβείτε στις Ρυθμίσεις > Ασφάλεια και Απόρρητο" + "Στη Διαχείριση κλειδιών κρυπτογράφησης, επιλέξτε Ανάκτηση κρυπτογραφημένων μηνυμάτων" + "Ακολουθήστε τις οδηγίες για να ενεργοποιήσετε την αποθήκευση κλειδιών" + "Επιστρέψτε στο %1$s" + "Ενεργοποιήστε την αποθήκευση κλειδιών σας πριν προχωρήσετε στο %1$s" "Έκδοση %1$s" "Σύνδεση χειροκίνητα" "Συνδέσου στο %1$s" diff --git a/features/login/impl/src/main/res/values-fa/translations.xml b/features/login/impl/src/main/res/values-fa/translations.xml index d903103c1b..c28c891c9a 100644 --- a/features/login/impl/src/main/res/values-fa/translations.xml +++ b/features/login/impl/src/main/res/values-fa/translations.xml @@ -15,6 +15,7 @@ "تغییر فراهم کنندهٔ حساب" "پلی گپگل" "ما نتوانستیم به این کارساز خانگی برسیم. لطفاً بررسی کنید که URL کارساز اصلی را به درستی وارد کرده اید. اگر URL صحیح است، برای کمک بیشتر با مدیر کارساز خانگی خود تماس بگیرید." + "سرور به دلیل مشکلی در فایل .well-known در دسترس نیست: %1$s" "نشانی کارساز خانگی" "ورود نشانی دامنه." "نشانی کارسازتان چیست؟" @@ -23,6 +24,7 @@ "این حساب حذف شده است." "نام کاربری یا گذرواژه نامعتبر است" "این یک شناسه کاربری معتبر نیست. قالب صحیح: ‪«@user:homeserver.or" + "این سرور برای استفاده از توکن‌های به‌روزرسانی پیکربندی شده است. این توکن‌ها هنگام استفاده از ورود مبتنی بر رمز عبور پشتیبانی نمی‌شوند." "کارساز اصلی انتخاب شده از رمز عبور یا ورود OAuth پشتیبانی نمی کند. لطفا با مدیر خود تماس بگیرید یا یک کارساز خانگی دیگر را انتخاب کنید." "جزییاتتان را وارد کنید" "ماتریکس شبکه‌ای بار برای ارتباطات نامتمرکز و امن است." diff --git a/features/login/impl/src/main/res/values-it/translations.xml b/features/login/impl/src/main/res/values-it/translations.xml index 3753d58390..1f1b51cda8 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -28,7 +28,7 @@ "Qual è l\'indirizzo del tuo server?" "Seleziona il tuo server" "Crea account" - "Questo account è stato disattivato." + "Questo account è stato eliminato." "Nome utente e/o password errati" "Questo non è un identità utente valida. il formato atteso é: \'@user:homeserver.org\'" "Questo server è configurato per usare i token di aggiornamento. Non sono supportati quando si usa l\'accesso basato su password." @@ -45,6 +45,7 @@ "Torna a %1$s" "Abilita l\'archivio delle chiavi prima di procedere con %1$s" "Versione %1$s" + "Verifica dell\'account" "Accedi manualmente" "Accedi a %1$s" "Accedi con codice QR" diff --git a/features/login/impl/src/main/res/values-pl/translations.xml b/features/login/impl/src/main/res/values-pl/translations.xml index b134395adf..ca0d035fe0 100644 --- a/features/login/impl/src/main/res/values-pl/translations.xml +++ b/features/login/impl/src/main/res/values-pl/translations.xml @@ -28,7 +28,7 @@ "Jaki jest adres Twojego serwera?" "Wybierz swój serwer" "Utwórz konto" - "To konto zostało dezaktywowane." + "To konto zostało usunięte." "Nieprawidłowa nazwa użytkownika i/lub hasło" "To nie jest prawidłowy identyfikator użytkownika. Oczekiwany format: \'@user:homeserver.org\'" "Ten serwer został skonfigurowany do korzystania z tokenów odświeżania. Nie są one obsługiwane, gdy korzystasz z hasła." @@ -37,11 +37,20 @@ "Matrix to otwarta sieć do bezpiecznej i zdecentralizowanej komunikacji." "Witaj ponownie!" "Zaloguj się do %1$s" + "Otwórz Element Classic" + "Otwórz Element Classic na swoim urządzeniu" + "Przejdź do Ustawienia > Bezpieczeństwo i prywatność" + "W Zarządzaniu kluczami kryptograficznymi wybierz przywracanie wiadomości szyfrowanych" + "Aby włączyć magazyn kluczy, postępuj zgodnie z instrukcjami" + "Wróć do %1$s" + "Włącz magazyn kluczy zanim przejdziesz do %1$s" "Wersja %1$s" + "Sprawdzanie konta" "Zaloguj się ręcznie" "Zaloguj się do %1$s" "Zaloguj się za pomocą kodu QR" "Utwórz konto" + "Witamy ponownie" "Witamy w %1$s. Szybszy i prostszy niż kiedykolwiek." "Witamy w %1$s. Doładowany, dla szybkości i prostoty." "Be in your element" @@ -60,6 +69,8 @@ "Prośba o logowanie została anulowana" "Logowanie zostało odrzucone na drugim urządzeniu." "Logowanie odrzucone" + "Nie musisz już robić nic więcej." + "Twoje drugie urządzenie jest już zalogowane" "Logowanie wygasło. Spróbuj ponownie." "Logowanie nie zostało ukończone na czas" "Twoje drugie urządzenie nie wspiera logowania się do %s za pomocą kodu QR. diff --git a/features/login/impl/src/main/res/values-uk/translations.xml b/features/login/impl/src/main/res/values-uk/translations.xml index 0d8eca42cf..17632cc4fc 100644 --- a/features/login/impl/src/main/res/values-uk/translations.xml +++ b/features/login/impl/src/main/res/values-uk/translations.xml @@ -28,7 +28,7 @@ "Яка адреса вашого сервера?" "Виберіть свій сервер" "Створити обліковий запис" - "Цей обліковий запис було деактивовано." + "Цей обліковий запис було видалено." "Неправильне ім\'я користувача та/або пароль" "Це недійсний ідентифікатор користувача. Очікуваний формат: \'@user:homeserver.org\'" "Цей сервер налаштований на використання оновлюваних токенів. Вони не підтримуються, якщо використовується вхід за допомогою основі пароля." @@ -37,11 +37,20 @@ "Matrix — це відкрита мережа для безпечної, децентралізованої комунікації." "З поверненням!" "Увійти в %1$s" + "Відкрити Element Classic" + "Відкрийте Element Classic на своєму пристрої" + "Перейдіть до «Налаштування» > «Безпека та конфіденційність»" + "У розділі «Управління криптографічними ключами» виберіть «Відновлення зашифрованих повідомлень»" + "Дотримуйтесь інструкцій, щоб увімкнути сховище ключів" + "Повернутися до %1$s" + "Увімкніть сховище ключів, перш ніж переходити до %1$s" "Версія %1$s" + "Перевірка облікового запису" "Увійти вручну" "Увійти в %1$s" "Увійти за допомогою QR-коду" "Створити обліковий запис" + "З поверненням!" "Ласкаво просимо до найшвидшого %1$s. Заряджений для швидкості та простоти." "Ласкаво просимо до %1$s. Заряджений, для швидкості та простоти." "Будьте у своєму element" diff --git a/features/logout/impl/src/main/res/values-fa/translations.xml b/features/logout/impl/src/main/res/values-fa/translations.xml index d286ded539..a540b9be37 100644 --- a/features/logout/impl/src/main/res/values-fa/translations.xml +++ b/features/logout/impl/src/main/res/values-fa/translations.xml @@ -4,15 +4,15 @@ "برداشتن این افزاره" "برداشتن این افزاره" "برداشتن افزاره…" - "دارید از واپسین نشستتان خارج می‌شوید. اگر اکنون خارج شوید پیام‌های رمزنگاشته‌تان را از دست خواهید داد." - "پشتیبان را خاموش کرده‌اید" - "در هنگامی که آفلاین شدید، کلیدهای شما هنوز در حال پشتیبان‌گیری بودند. دوباره متصل شوید ، تا قبل از خروج از کلیدهایتان نسخه پشتیبان‌ گرفته شود." + "این تنها دستگاه شماست. اگر آن را جدا کنید، برای تأیید هویت دیجیتال خود و بازیابی چت‌های رمزگذاری شده‌تان در دفعه بعد که وارد سیستم می‌شوید، به یک کلید بازیابی نیاز خواهید داشت." + "شما در درحال از دست دادن دسترسی به چت‌های رمزگذاری‌شده‌تان هستید." + "وقتی آفلاین شدید، کلیدهای شما هنوز در حال پشتیبان‌گیری بودند. دوباره متصل شوید تا قبل از جدا کردن این دستگاه، از کلیدهایتان پشتیبان‌گیری شود." "کلیدهایتان هنوز در حال پشتیبان گیریند" - "لطفاً پیش از خروج منتظر پایانش شوید." + "لطفاً قبل از خروج از این دستگاه، منتظر بمانید تا این مراحل تکمیل شود." "کلیدهایتان هنوز در حال پشتیبان گیریند" "برداشتن این افزاره" - "شما در آستانه خروج از آخرین جلسه خود هستید. اگر اکنون از سیستم خارج شوید، دسترسی به پیام های رمزگذاری شده تان را از دست خواهید داد." - "بازگردانی برپا نشده" - "دارید از واپسین نشستتان خارج می‌شوید. اگر اکنون خارج شوید ممکن است پیام‌های رمزنگاشته‌تان را از دست بدهید." - "کلید بازیابیتان را ذخیره کرده‌اید؟" + "این تنها دستگاه شماست. اگر آن را جدا کنید، برای تأیید هویت دیجیتال خود و بازیابی چت‌های رمزگذاری شده‌تان در دفعه بعد که وارد سیستم می‌شوید، به یک کلید بازیابی نیاز خواهید داشت." + "شما در حال از دست دادن دسترسی به چت‌های رمزگذاری‌شده‌تان هستید." + "این تنها دستگاه شماست. اگر آن را جدا کنید، برای تأیید هویت دیجیتال خود و بازیابی چت‌های رمزگذاری شده‌تان در دفعه بعد که وارد سیستم می‌شوید، به یک کلید بازیابی نیاز خواهید داشت." + "قبل از حذف این دستگاه، مطمئن شوید که به کلید بازیابی خود دسترسی دارید." diff --git a/features/logout/impl/src/main/res/values-pl/translations.xml b/features/logout/impl/src/main/res/values-pl/translations.xml index 46a5c2d6bd..691255f434 100644 --- a/features/logout/impl/src/main/res/values-pl/translations.xml +++ b/features/logout/impl/src/main/res/values-pl/translations.xml @@ -1,18 +1,18 @@ - "Czy na pewno chcesz się wylogować?" - "Wyloguj" - "Wyloguj" - "Wylogowywanie…" - "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." - "Wyłączyłeś backup" - "Twoje klucze były nadal archiwizowane po przejściu w tryb offline. Połącz się ponownie, aby zapisać w chmurze przed wylogowaniem." + "Czy na pewno chcesz usunąć to urządzenie?" + "Usuń to urządzenie" + "Usuń to urządzenie" + "Usuwam urządzenie…" + "To jest twoje jedyne urządzenie. Jeśli je usuniesz, będziesz potrzebować klucza przywracania, aby potwierdzić swoją tożsamość cyfrową i przywrócić zaszyfrowane czaty przy następnym logowaniu." + "Zamierzasz utracić dostęp do swoich zaszyfrowanych czatów" + "Twoje klucze były nadal archiwizowane po przejściu w tryb offline. Połącz się ponownie, aby zapisać je w chmurze przed usunięciem urządzenia." "Twoje klucze są nadal archiwizowane" - "Zanim się wylogujesz, poczekaj na zakończenie operacji." + "Poczekaj na zakończenie procesu, zanim usuniesz to urządzenie." "Twoje klucze są nadal archiwizowane" - "Wyloguj" - "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." - "Nie ustawiono przywracania" - "Zamierzasz wylogować się ze swojej ostatniej sesji. Jeśli wylogujesz się teraz, stracisz dostęp do swoich wiadomości szyfrowanych." - "Czy zapisałeś swój klucz przywracania?" + "Usuń to urządzenie" + "To jest twoje jedyne urządzenie. Jeśli je usuniesz, będziesz potrzebować klucza przywracania, aby potwierdzić swoją tożsamość cyfrową i przywrócić zaszyfrowane czaty przy następnym logowaniu." + "Zamierzasz utracić dostęp do swoich zaszyfrowanych czatów" + "To jest twoje jedyne urządzenie. Jeśli je usuniesz, będziesz potrzebować klucza przywracania, aby potwierdzić swoją tożsamość cyfrową i przywrócić zaszyfrowane czaty przy następnym logowaniu." + "Upewnij się, że posiadasz dostęp do klucza przywracania przed usunięciem urządzenia" diff --git a/features/logout/impl/src/main/res/values-sk/translations.xml b/features/logout/impl/src/main/res/values-sk/translations.xml index 39301437fb..4fe07b2fa7 100644 --- a/features/logout/impl/src/main/res/values-sk/translations.xml +++ b/features/logout/impl/src/main/res/values-sk/translations.xml @@ -1,16 +1,16 @@ - "Ste si istí, že sa chcete odhlásiť?" - "Odhlásiť sa" - "Odhlásiť sa" - "Prebieha odhlasovanie…" + "Naozaj chcete odstrániť toto zariadenie?" + "Odstrániť toto zariadenie" + "Odstrániť toto zariadenie" + "Odoberanie zariadenia…" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, stratíte prístup k svojim šifrovaným správam." "Vypli ste zálohovanie" "Keď ste sa odpojili od internetu, vaše kľúče sa ešte stále zálohovali. Pripojte sa znova k internetu, aby sa vaše kľúče mohli zálohovať pred odhlásením." "Vaše kľúče sa ešte stále zálohujú" "Pred odhlásením počkajte, kým sa to dokončí." "Vaše kľúče sa ešte stále zálohujú" - "Odhlásiť sa" + "Odstrániť toto zariadenie" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, stratíte prístup k svojim šifrovaným správam." "Obnovenie nie je nastavené" "Chystáte sa odhlásiť z vašej poslednej relácie. Ak sa teraz odhlásite, môžete stratiť prístup k svojim šifrovaným správam." diff --git a/features/logout/impl/src/main/res/values-uk/translations.xml b/features/logout/impl/src/main/res/values-uk/translations.xml index 7e23189dc6..f012603533 100644 --- a/features/logout/impl/src/main/res/values-uk/translations.xml +++ b/features/logout/impl/src/main/res/values-uk/translations.xml @@ -1,9 +1,9 @@ - "Ви впевнені, що бажаєте вийти?" + "Ви впевнені, що хочете видалити цей пристрій?" "Вийти" "Вийти" - "Вихід…" + "Видалення пристрою…" "Ви збираєтеся вийти зі свого останнього сеансу. Якщо ви вийдете зараз, ви втратите доступ до своїх зашифрованих повідомлень." "Ви вимкнули резервне копіювання" "Коли ви вийшли з мережі, резервна копія ваших ключів все ще створювалася. Повторно під\'єднайтеся, щоб зберегти резервну копію ключів перед виходом." diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt index bef8ca84d6..4d621e417f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesEvent.kt @@ -18,6 +18,8 @@ sealed interface MessagesEvent { data class ToggleReaction(val emoji: String, val eventOrTransactionId: EventOrTransactionId) : MessagesEvent data class InviteDialogDismissed(val action: InviteDialogAction) : MessagesEvent data class OnUserClicked(val user: MatrixUser) : MessagesEvent + data object StopLiveLocationShare : MessagesEvent + data object ShowLiveLocationShare : MessagesEvent data object MarkAsFullyReadAndExit : MessagesEvent } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt index 7b0515a423..d20dc4b38e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesFlowNode.kt @@ -278,6 +278,10 @@ class MessagesFlowNode( backstack.push(NavTarget.EditPoll(Timeline.Mode.Live, eventId)) } + override fun navigateToCurrentLiveLocation() { + backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + } + override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { val callData = CallData( sessionId = sessionId, @@ -513,6 +517,10 @@ class MessagesFlowNode( backstack.push(NavTarget.EditPoll(Timeline.Mode.Thread(navTarget.threadRootId), eventId)) } + override fun navigateToCurrentLiveLocation() { + backstack.push(NavTarget.LocationViewer(ShowLocationMode.Live(senderId = sessionId))) + } + override fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) { val callData = CallData( sessionId = sessionId, @@ -646,6 +654,7 @@ class MessagesFlowNode( filename = content.filename, fileSize = content.fileSize, caption = content.caption, + formattedCaption = content.formattedCaption, mimeType = content.mimeType, formattedFileSize = content.formattedFileSize, fileExtension = content.fileExtension, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt index e475f579c3..6113b68aab 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNavigator.kt @@ -26,5 +26,6 @@ interface MessagesNavigator { fun navigateToMember(userId: UserId) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToDeveloperSettings() + fun navigateToCurrentLiveLocation() fun close() } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt index 308cda506e..a9ce2f5ba1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt @@ -127,6 +127,7 @@ class MessagesNode( fun navigateToSendLocation() fun navigateToCreatePoll() fun navigateToEditPoll(eventId: EventId) + fun navigateToCurrentLiveLocation() fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToRoomDetails() @@ -239,6 +240,10 @@ class MessagesNode( callback.navigateToDeveloperSettings() } + override fun navigateToCurrentLiveLocation() { + callback.navigateToCurrentLiveLocation() + } + private fun displaySameRoomToast() { context.toast(CommonStrings.screen_room_permalink_same_room_android) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 5271906fff..6754d703a3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -27,6 +27,8 @@ import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject import im.vector.app.features.analytics.plan.PinUnpinAction import io.element.android.appconfig.MessageComposerConfig +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager +import io.element.android.features.location.api.live.isCurrentlySharing import io.element.android.features.messages.api.timeline.HtmlConverterProvider import io.element.android.features.messages.impl.MessagesState.Threads import io.element.android.features.messages.impl.actionlist.ActionListState @@ -77,8 +79,8 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState +import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId import io.element.android.libraries.matrix.ui.messages.reply.map import io.element.android.libraries.matrix.ui.model.getAvatarData @@ -126,6 +128,7 @@ class MessagesPresenter( private val featureFlagService: FeatureFlagService, private val addRecentEmoji: AddRecentEmoji, private val markAsFullyRead: MarkAsFullyRead, + private val liveLocationShareManager: ActiveLiveLocationShareManager, @SessionCoroutineScope private val sessionCoroutineScope: CoroutineScope, ) : Presenter { @AssistedFactory @@ -172,6 +175,7 @@ class MessagesPresenter( } val canOpenThreadList by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomThreadList).collectAsState(initial = false) + val isCurrentlySharingLiveLocationInRoom by remember { liveLocationShareManager.isCurrentlySharing(room.roomId) }.collectAsState() val userEventPermissions by room.permissionsAsState(UserEventPermissions.DEFAULT) { perms -> perms.userEventPermissions() @@ -260,6 +264,18 @@ class MessagesPresenter( is MessagesEvent.OnUserClicked -> { roomMemberModerationState.eventSink(RoomMemberModerationEvents.ShowActionsForUser(event.user)) } + MessagesEvent.StopLiveLocationShare -> { + localCoroutineScope.launch { + liveLocationShareManager.stopShare(room.roomId) + .onFailure { + Timber.e(it, "Failed to stop live location share for roomId=${room.roomId}") + snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_error)) + } + } + } + MessagesEvent.ShowLiveLocationShare -> { + navigator.navigateToCurrentLiveLocation() + } is MessagesEvent.MarkAsFullyReadAndExit -> if (!markingAsReadAndExiting.getAndSet(true)) { coroutineScope.launch { val latestEventId = room.liveTimeline.getLatestEventId().getOrElse { @@ -311,6 +327,7 @@ class MessagesPresenter( // TODO calculate this properly based on the thread list and the read state of each thread hasUnreadThreads = false, ), + showLiveLocationShareBanner = isCurrentlySharingLiveLocationInRoom && timelineState.timelineMode !is Timeline.Mode.Thread, eventSink = ::handleEvent, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 862f30832b..a16485c6f7 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -58,6 +58,7 @@ data class MessagesState( val topBarSharedHistoryIcon: SharedHistoryIcon, val successorRoom: SuccessorRoom?, val threads: Threads, + val showLiveLocationShareBanner: Boolean, val eventSink: (MessagesEvent) -> Unit ) { val isTombstoned = successorRoom != null diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 14c83db833..6389089e07 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -80,6 +80,7 @@ open class MessagesStateProvider : PreviewParameterProvider { currentPinnedMessageIndex = 0, ), ), + aMessagesState(isCurrentlySharingLiveLocationInRoom = true), aMessagesState(successorRoom = SuccessorRoom(RoomId("!id:domain"), null)), aMessagesState( timelineState = aTimelineState( @@ -127,6 +128,7 @@ fun aMessagesState( hasThreads = false, hasUnreadThreads = false, ), + isCurrentlySharingLiveLocationInRoom: Boolean = false, eventSink: (MessagesEvent) -> Unit = {}, ) = MessagesState( roomId = RoomId("!id:domain"), @@ -156,6 +158,7 @@ fun aMessagesState( topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = successorRoom, threads = threads, + showLiveLocationShareBanner = isCurrentlySharingLiveLocationInRoom, eventSink = eventSink, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 5a0b14b820..3e6f14e805 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -56,6 +56,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.location.api.LiveLocationSharingBanner import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerEvent import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListView @@ -205,15 +206,15 @@ fun MessagesView( val expandableState = rememberExpandableBottomSheetLayoutState() ExpandableBottomSheetLayout( modifier = modifier - .fillMaxSize() - .imePadding() - .systemBarsPadding() - .onSizeChanged { size -> - // Let the composer takes at max half of the available height. - // The value will be different if the soft keyboard is displayed - // or not. - maxComposerHeightPx = (size.height * 0.5f).toInt() - }, + .fillMaxSize() + .imePadding() + .systemBarsPadding() + .onSizeChanged { size -> + // Let the composer takes at max half of the available height. + // The value will be different if the soft keyboard is displayed + // or not. + maxComposerHeightPx = (size.height * 0.5f).toInt() + }, content = { Scaffold( contentWindowInsets = WindowInsets.statusBars, @@ -250,8 +251,8 @@ fun MessagesView( content = { padding -> Box( modifier = Modifier - .padding(padding) - .consumeWindowInsets(padding) + .padding(padding) + .consumeWindowInsets(padding) ) { MessagesViewContent( state = state, @@ -288,10 +289,10 @@ fun MessagesView( SuggestionsPickerView( modifier = Modifier - .shadow(10.dp) - .background(ElementTheme.colors.bgCanvasDefault) - .align(Alignment.BottomStart) - .heightIn(max = 230.dp), + .shadow(10.dp) + .background(ElementTheme.colors.bgCanvasDefault) + .align(Alignment.BottomStart) + .heightIn(max = 230.dp), roomId = state.roomId, roomName = state.roomName, roomAvatarData = state.roomAvatar, @@ -467,9 +468,9 @@ private fun MessagesViewContent( ) { Box( modifier = modifier - .fillMaxSize() - .navigationBarsPadding() - .imePadding(), + .fillMaxSize() + .navigationBarsPadding() + .imePadding(), ) { AttachmentsBottomSheet( state = state.composerState, @@ -520,25 +521,34 @@ private fun MessagesViewContent( ) if (state.timelineState.timelineMode !is Timeline.Mode.Thread) { - AnimatedVisibility( - visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, - modifier = Modifier.onSizeChanged { pinnedBannerHeightDp = with(density) { it.height.toDp() } }, - enter = expandVertically(), - exit = shrinkVertically(), - ) { - fun focusOnPinnedEvent(eventId: EventId) { - state.timelineState.eventSink( - TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + Column { + AnimatedVisibility( + visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible, + modifier = Modifier.onSizeChanged { pinnedBannerHeightDp = with(density) { it.height.toDp() } }, + enter = expandVertically(), + exit = shrinkVertically(), + ) { + fun focusOnPinnedEvent(eventId: EventId) { + state.timelineState.eventSink( + TimelineEvent.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds) + ) + } + PinnedMessagesBannerView( + state = state.pinnedMessagesBannerState, + onClick = ::focusOnPinnedEvent, + onViewAllClick = onViewAllPinnedMessagesClick, + ) + } + if (state.showLiveLocationShareBanner) { + LiveLocationSharingBanner( + onClick = { state.eventSink(MessagesEvent.ShowLiveLocationShare) }, + onStopClick = { state.eventSink(MessagesEvent.StopLiveLocationShare) } ) } - PinnedMessagesBannerView( - state = state.pinnedMessagesBannerState, - onClick = ::focusOnPinnedEvent, - onViewAllClick = onViewAllPinnedMessagesClick, - ) } - knockRequestsBannerView() } + + knockRequestsBannerView() } } } @@ -587,9 +597,9 @@ private fun MessagesViewComposerBottomSheetContents( private fun CantSendMessageBanner() { Row( modifier = Modifier - .fillMaxWidth() - .background(ElementTheme.colors.bgSubtleSecondary) - .padding(16.dp), + .fillMaxWidth() + .background(ElementTheme.colors.bgSubtleSecondary) + .padding(16.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt index a69c6d7612..56bac5be33 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListStateProvider.kt @@ -15,6 +15,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser import io.element.android.features.messages.impl.crypto.sendfailure.resolve.anUnsignedDeviceSendFailure import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.aTimelineItemReactions +import io.element.android.features.messages.impl.timeline.model.event.aStaticLocationMode import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemFileContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent @@ -127,7 +128,7 @@ open class ActionListStateProvider : PreviewParameterProvider { anActionListState( target = ActionListState.Target.Success( event = aTimelineItemEvent( - content = aTimelineItemLocationContent(), + content = aTimelineItemLocationContent(mode = aStaticLocationMode()), timelineItemReactions = reactionsState ), sentTimeFull = "January 1, 1970 at 12:00 AM", @@ -140,7 +141,7 @@ open class ActionListStateProvider : PreviewParameterProvider { anActionListState( target = ActionListState.Target.Success( event = aTimelineItemEvent( - content = aTimelineItemLocationContent(), + content = aTimelineItemLocationContent(mode = aStaticLocationMode()), timelineItemReactions = reactionsState ), sentTimeFull = "January 1, 1970 at 12:00 AM", diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index 90b91691a9..d93fe0ee86 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -57,7 +57,6 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.draft.ComposerDraft import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType import io.element.android.libraries.matrix.api.room.getDirectRoomMember -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.use import io.element.android.libraries.matrix.api.timeline.TimelineException import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt index 3d18db12d9..ef2362c794 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/suggestions/SuggestionsPickerView.kt @@ -190,6 +190,7 @@ internal fun SuggestionsPickerViewPreview() { isIgnored = false, role = RoomMember.Role.User, membershipChangeReason = null, + isServiceMember = false, ) val anAlias = remember { RoomAlias("#room:domain.org") } SuggestionsPickerView( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index 6cd037484d..9e5f5ba304 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -44,7 +44,6 @@ import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.ui.strings.CommonStrings diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt index 0c58316b5e..be573fa92f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/ThreadedMessagesNode.kt @@ -67,7 +67,6 @@ import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.alias.matches import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo -import io.element.android.libraries.mediaplayer.api.MediaPlayer import io.element.android.libraries.ui.utils.a11y.hasExternalKeyboard import io.element.android.libraries.ui.utils.a11y.isTalkbackActive import io.element.android.services.analytics.api.AnalyticsService @@ -88,7 +87,6 @@ class ThreadedMessagesNode( private val presenterFactory: MessagesPresenter.Factory, private val actionListPresenterFactory: ActionListPresenter.Factory, private val timelineItemPresenterFactories: TimelineItemPresenterFactories, - private val mediaPlayer: MediaPlayer, private val permalinkParser: PermalinkParser, private val appNavigationStateService: AppNavigationStateService, private val roomMemberModerationRenderer: RoomMemberModerationRenderer, @@ -136,6 +134,7 @@ class ThreadedMessagesNode( fun navigateToSendLocation() fun navigateToCreatePoll() fun navigateToEditPoll(eventId: EventId) + fun navigateToCurrentLiveLocation() fun navigateToRoomCall(roomId: RoomId, isAudioCall: Boolean) fun navigateToThread(threadRootId: ThreadId, focusedEventId: EventId?) fun navigateToDeveloperSettings() @@ -156,9 +155,6 @@ class ThreadedMessagesNode( onStop = { appNavigationStateService.onLeavingThread(id) }, - onDestroy = { - mediaPlayer.close() - } ) } @@ -248,6 +244,11 @@ class ThreadedMessagesNode( callback.navigateToDeveloperSettings() } + override fun navigateToCurrentLiveLocation() { + // Shouldn't happen because LiveLocationSharingBanner is not shown in threads. + callback.navigateToCurrentLiveLocation() + } + override fun close() = navigateUp() @Composable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index edd8d446dc..0b99c45e06 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.setValue import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedFactory import dev.zacsweers.metro.AssistedInject +import io.element.android.features.location.api.live.ActiveLiveLocationShareManager import io.element.android.features.messages.impl.MessagesNavigator import io.element.android.features.messages.impl.UserEventPermissions import io.element.android.features.messages.impl.crypto.sendfailure.resolve.ResolveVerifiedUserSendFailureEvent @@ -48,7 +49,6 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UniqueId import io.element.android.libraries.matrix.api.core.asEventId import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomMembers import io.element.android.libraries.matrix.api.timeline.ReceiptType @@ -94,6 +94,7 @@ class TimelinePresenter( private val roomCallStatePresenter: Presenter, private val featureFlagService: FeatureFlagService, private val analyticsService: AnalyticsService, + private val liveLocationShareManager: ActiveLiveLocationShareManager, ) : Presenter { private val tag = "TimelinePresenter" @@ -200,7 +201,9 @@ class TimelinePresenter( is TimelineEvent.EditPoll -> { navigator.navigateToEditPoll(event.pollStartId) } - is TimelineEvent.StopLiveLocationShare -> Unit + is TimelineEvent.StopLiveLocationShare -> sessionCoroutineScope.launch { + liveLocationShareManager.stopShare(room.roomId) + } is TimelineEvent.FocusOnEvent -> sessionCoroutineScope.launch { focusRequestState.value = FocusRequestState.Requested(event.eventId, event.debounce) delay(event.debounce) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt index dfd1b2ed0e..61273ff07a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemCallNotifyView.kt @@ -8,6 +8,7 @@ package io.element.android.features.messages.impl.timeline.components +import androidx.annotation.StringRes import androidx.compose.foundation.border import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement @@ -22,17 +23,19 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.timeline.TimelineRoomInfo import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.aTimelineRoomInfo import io.element.android.features.messages.impl.timeline.model.TimelineItem +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent -import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.modifiers.onKeyboardContextMenuAction import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -42,6 +45,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun TimelineItemCallNotifyView( + timelineRoomInfo: TimelineRoomInfo, event: TimelineItem.Event, content: TimelineItemRtcNotificationContent, onLongClick: (TimelineItem.Event) -> Unit, @@ -62,37 +66,22 @@ internal fun TimelineItemCallNotifyView( horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically, ) { - Avatar( - avatarData = event.senderAvatar, - avatarType = AvatarType.User, + Icon( + modifier = Modifier.size(20.sp.toDp()), + imageVector = getIcon(timelineRoomInfo, content), + contentDescription = null, + tint = ElementTheme.colors.iconSecondary, ) - Column(modifier = Modifier.weight(1f)) { - Text( - text = event.safeSenderName, - style = ElementTheme.typography.fontBodyLgMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - modifier = Modifier.size(20.sp.toDp()), - imageVector = - if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid(), - contentDescription = null, - tint = ElementTheme.colors.iconSecondary, - ) - Text( - text = stringResource(CommonStrings.common_call_started), - style = ElementTheme.typography.fontBodyMdRegular, - color = ElementTheme.colors.textSecondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } - } + + Text( + modifier = Modifier.weight(1f), + text = stringResource(getTextRes(timelineRoomInfo, content)), + style = ElementTheme.typography.fontBodyMdRegular, + color = ElementTheme.colors.textSecondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + Text( text = event.sentTime, style = ElementTheme.typography.fontBodyMdRegular, @@ -103,19 +92,56 @@ internal fun TimelineItemCallNotifyView( } } +@StringRes +private fun getTextRes( + timelineRoomInfo: TimelineRoomInfo, + content: TimelineItemRtcNotificationContent +): Int = if (timelineRoomInfo.isDm) { + when (content.state) { + is RtcNotificationState.Declined -> { + if (content.state.byMe) CommonStrings.common_call_you_declined else CommonStrings.common_call_declined + } + RtcNotificationState.Started -> CommonStrings.common_call_started + } +} else { + // In Rooms, do not show declined info. + CommonStrings.common_call_started +} + +@Composable +private fun getIcon( + timelineRoomInfo: TimelineRoomInfo, + content: TimelineItemRtcNotificationContent +): ImageVector { + val showAsDeclined = timelineRoomInfo.isDm && content.state is RtcNotificationState.Declined + val icon = if (showAsDeclined) { + if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallDeclinedSolid() else CompoundIcons.VideoCallDeclinedSolid() + } else { + if (content.callIntent == CallIntent.AUDIO) CompoundIcons.VoiceCallSolid() else CompoundIcons.VideoCallSolid() + } + return icon +} + @PreviewsDayNight @Composable internal fun TimelineItemCallNotifyViewPreview() = ElementPreview { - Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { - listOf( - TimelineItemRtcNotificationContent(CallIntent.AUDIO), - TimelineItemRtcNotificationContent(CallIntent.VIDEO), - ).forEach { content -> - TimelineItemCallNotifyView( - event = aTimelineItemEvent(content = content), - content = content, - onLongClick = {}, - ) + Column(modifier = Modifier.padding(2.dp), verticalArrangement = Arrangement.spacedBy(2.dp)) { + listOf(false, true).forEach { isDm -> + listOf(CallIntent.AUDIO, CallIntent.VIDEO).forEach { callIntent -> + listOf( + RtcNotificationState.Started, + RtcNotificationState.Declined(byMe = false), + RtcNotificationState.Declined(byMe = true), + ).forEach { state -> + val content = TimelineItemRtcNotificationContent(callIntent, state) + TimelineItemCallNotifyView( + timelineRoomInfo = aTimelineRoomInfo(isDm = isDm), + event = aTimelineItemEvent(content = content), + content = content, + onLongClick = {}, + ) + } + } } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 5785627564..936028cbd6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -783,7 +783,7 @@ private fun MessageEventBubbleContent( val content = content.ensureActiveLiveLocation() val shouldHide = content.mode is TimelineItemLocationContent.Mode.Live && content.mode.isActive && - content.mode.canStop + content.mode.isOwnUser if (shouldHide) TimestampPosition.Hidden else TimestampPosition.Overlay } is TimelineItemPollContent -> TimestampPosition.Below diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt index 842b7a08f5..a02413d534 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemRow.kt @@ -125,6 +125,7 @@ internal fun TimelineItemRow( is TimelineItemRtcNotificationContent -> { TimelineItemCallNotifyView( modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 16.dp), + timelineRoomInfo = timelineRoomInfo, event = timelineItem, content = timelineItem.content, onLongClick = onLongClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt index f00b6b0b5b..4ab4ee84a6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemLocationView.kt @@ -13,14 +13,12 @@ import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -77,13 +75,14 @@ private fun LiveLocationOverlay( Row( modifier = modifier .fillMaxWidth() - .background(ElementTheme.colors.bgCanvasDefault.copy(alpha = 0.9f)) - .padding(horizontal = 8.dp, vertical = 8.dp), + .background(ElementTheme.colors.bgCanvasDefault.copy(alpha = 0.9f)), verticalAlignment = Alignment.CenterVertically, ) { val iconShape = RoundedCornerShape(8.dp) Box( modifier = Modifier + // Ensure this Box uses same spacings than the Stop IconButton. + .minimumInteractiveComponentSize() .size(32.dp) .border( width = 1.dp, @@ -120,7 +119,6 @@ private fun LiveLocationOverlay( ) } } - Spacer(Modifier.width(8.dp)) Column(modifier = Modifier.weight(1f)) { Text( text = if (mode.isActive) { @@ -140,13 +138,16 @@ private fun LiveLocationOverlay( } } - if (mode.isActive && mode.canStop) { + if (mode.canStopSharing) { IconButton( onClick = onStopClick, colors = IconButtonDefaults.iconButtonColors( containerColor = ElementTheme.colors.bgCriticalPrimary, contentColor = ElementTheme.colors.iconOnSolidPrimary, - ) + ), + modifier = Modifier + .minimumInteractiveComponentSize() + .size(30.dp) ) { Icon( imageVector = CompoundIcons.Stop(), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt index 7c36521fc0..0d51d9f5b8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/di/FakeTimelineItemPresenterFactories.kt @@ -8,7 +8,9 @@ package io.element.android.features.messages.impl.timeline.di +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent +import io.element.android.features.messages.impl.timeline.model.event.ensureActiveLiveLocation import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.voiceplayer.api.VoiceMessageState import io.element.android.libraries.voiceplayer.api.aVoiceMessageState @@ -18,6 +20,12 @@ import io.element.android.libraries.voiceplayer.api.aVoiceMessageState */ fun aFakeTimelineItemPresenterFactories() = TimelineItemPresenterFactories( mapOf( + Pair( + TimelineItemLocationContent::class, + TimelineItemPresenterFactory { content -> + Presenter { content.ensureActiveLiveLocation() } + }, + ), Pair( TimelineItemVoiceContent::class, TimelineItemPresenterFactory { Presenter { aVoiceMessageState() } }, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt index dff195e833..3b3e5118d6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentFactory.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.timeline.factories.event import dev.zacsweers.metro.Inject import io.element.android.features.location.api.Location +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent @@ -104,7 +105,12 @@ class TimelineItemContentFactory( is PollContent -> pollFactory.create(eventId, isEditable, isOutgoing, itemContent) is UnableToDecryptContent -> utdFactory.create(itemContent) is CallNotifyContent -> TimelineItemRtcNotificationContent( - itemContent.callIntent + callIntent = itemContent.callIntent, + state = if (itemContent.declinedBy.isEmpty()) { + RtcNotificationState.Started + } else { + RtcNotificationState.Declined(itemContent.declinedBy.any { it == sessionId }) + } ) is UnknownContent -> TimelineItemUnknownContent is LiveLocationContent -> { @@ -127,6 +133,7 @@ class TimelineItemContentFactory( isActive = itemContent.isLive, endsAt = stringProvider.getString(CommonStrings.common_ends_at, endsAt), endTimestamp = itemContent.endTimestamp, + isOwnUser = sessionId == sender ), ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt index 44dd2df38d..52e008e121 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemEventContentProvider.kt @@ -27,7 +27,7 @@ class TimelineItemEventContentProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - aTimelineItemLocationContent(), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = true, - endsAt = "Ends at 12:34", - endTimestamp = 0L, - canStop = true, - lastKnownLocation = aLocation() - ), + mode = aStaticLocationMode() ), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = true, - endsAt = "Ends at 12:34", - endTimestamp = 0L, - lastKnownLocation = aLocation() - ), + mode = aLiveLocationMode(isActive = true) ), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = true, - endsAt = "Ends at 12:34", - endTimestamp = 0L, - lastKnownLocation = null - ), + mode = aLiveLocationMode(isActive = true, lastKnownLocation = null) ), aTimelineItemLocationContent( - mode = TimelineItemLocationContent.Mode.Live( - isActive = false, - endsAt = "", - endTimestamp = 0L, - lastKnownLocation = aLocation() - ), + mode = aLiveLocationMode(isActive = true, isOwnUser = false) + ), + aTimelineItemLocationContent( + mode = aLiveLocationMode(isActive = false) ), ) } +fun aLiveLocationMode( + isActive: Boolean, + isOwnUser: Boolean = true, + lastKnownLocation: Location? = aLocation(), + endsAt: String = "Ends at 12:34", + endTimestamp: Long = 0L, +): TimelineItemLocationContent.Mode = TimelineItemLocationContent.Mode.Live( + isActive = isActive, + endsAt = endsAt, + endTimestamp = endTimestamp, + isOwnUser = isOwnUser, + lastKnownLocation = lastKnownLocation +) + +fun aStaticLocationMode(location: Location = aLocation()) = TimelineItemLocationContent.Mode.Static(location) fun aTimelineItemLocationContent( senderId: UserId = UserId("@sender:matrix.org"), senderProfile: ProfileDetails = aProfileDetailsReady(), description: String? = null, - mode: TimelineItemLocationContent.Mode = TimelineItemLocationContent.Mode.Static(aLocation()), + mode: TimelineItemLocationContent.Mode, ) = TimelineItemLocationContent( senderId = senderId, senderProfile = senderProfile, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt index 53facfc675..2359f196a9 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRtcNotificationContent.kt @@ -9,7 +9,19 @@ package io.element.android.features.messages.impl.timeline.model.event import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.api.timeline.item.event.EventType -class TimelineItemRtcNotificationContent(val callIntent: CallIntent) : TimelineItemEventContent { - override val type: String = "org.matrix.msc4075.rtc.notification" +// State of the call, for now only isDeclined but in the future could be missed, active. +sealed interface RtcNotificationState { + /** Some users have declined, byMe indicates if the current user is one of them. */ + data class Declined(val byMe: Boolean) : RtcNotificationState + + object Started : RtcNotificationState +} + +class TimelineItemRtcNotificationContent( + val callIntent: CallIntent, + val state: RtcNotificationState, +) : TimelineItemEventContent { + override val type: String = EventType.RTC_NOTIFICATION } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt index c48f2dae40..210e123595 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/utils/messagesummary/DefaultMessageSummaryFormatter.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.utils.messagesummary import android.content.Context import dev.zacsweers.metro.ContributesBinding +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEventContent @@ -56,7 +57,16 @@ class DefaultMessageSummaryFormatter( is TimelineItemFileContent -> context.getString(CommonStrings.common_file) is TimelineItemAudioContent -> context.getString(CommonStrings.common_audio) is TimelineItemLegacyCallInviteContent -> context.getString(CommonStrings.common_unsupported_call) - is TimelineItemRtcNotificationContent -> context.getString(CommonStrings.common_call_started) + is TimelineItemRtcNotificationContent -> when (content.state) { + is RtcNotificationState.Declined -> { + if (content.state.byMe) { + context.getString(CommonStrings.common_call_you_declined) + } else { + context.getString(CommonStrings.common_call_declined) + } + } + RtcNotificationState.Started -> context.getString(CommonStrings.common_call_started) + } } // Truncate the message to a safe length to avoid crashes in Compose .toSafeLength() diff --git a/features/messages/impl/src/main/res/values-fa/translations.xml b/features/messages/impl/src/main/res/values-fa/translations.xml index dcac058d2f..19f55a5559 100644 --- a/features/messages/impl/src/main/res/values-fa/translations.xml +++ b/features/messages/impl/src/main/res/values-fa/translations.xml @@ -56,5 +56,13 @@ "این اتاق جایگزین شده و دیگر فعّال نیست" "دیدن پیام‌های قدیمی" "این اتاق ادامهٔ اتاقی دیگر است" + + "%1$s، %2$s و %3$d سایر" + "%1$s، %2$s و %3$d موارد دیگر" + + + "%1$s در حال تایپ است" + "%1$s در حال تایپ هستند" + "%1$s و %2$s" diff --git a/features/messages/impl/src/main/res/values-pl/translations.xml b/features/messages/impl/src/main/res/values-pl/translations.xml index 18a8af6cb0..0085e1d4ee 100644 --- a/features/messages/impl/src/main/res/values-pl/translations.xml +++ b/features/messages/impl/src/main/res/values-pl/translations.xml @@ -35,7 +35,7 @@ "Nagraj film" "Załącznik" "Zdjęcia i filmy" - "Lokalizacja" + "Udostępnij lokalizację" "Ankieta" "Formatowanie tekstu" "Historia wiadomości jest obecnie niedostępna." diff --git a/features/messages/impl/src/main/res/values-sk/translations.xml b/features/messages/impl/src/main/res/values-sk/translations.xml index 4f267d8552..d2022c4882 100644 --- a/features/messages/impl/src/main/res/values-sk/translations.xml +++ b/features/messages/impl/src/main/res/values-sk/translations.xml @@ -35,7 +35,7 @@ "Nahrať video" "Príloha" "Knižnica fotografií a videí" - "Poloha" + "Zdieľať polohu" "Anketa" "Formátovanie textu" "História správ v tejto miestnosti nie je momentálne k dispozícii" diff --git a/features/messages/impl/src/main/res/values-uk/translations.xml b/features/messages/impl/src/main/res/values-uk/translations.xml index c51744a408..a3035e9e08 100644 --- a/features/messages/impl/src/main/res/values-uk/translations.xml +++ b/features/messages/impl/src/main/res/values-uk/translations.xml @@ -35,7 +35,7 @@ "Записати відео" "Вкладення" "Бібліотека фото та відео" - "Розташування" + "Поділитися місцеперебуванням" "Опитування" "Форматування тексту" "Історія повідомлень наразі недоступна." diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt index 44d82f1a7c..68f9a8d17a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/FakeMessagesNavigator.kt @@ -28,6 +28,7 @@ class FakeMessagesNavigator( private val navigateToDeveloperSettingsLambda: () -> Unit = { lambdaError() }, private val onOpenThreadLambda: (threadRootId: ThreadId, focusedEventId: EventId?) -> Unit = { _, _ -> lambdaError() }, private val closeLambda: () -> Unit = { lambdaError() }, + private val navigateToCurrentLiveLocationLambda: () -> Unit = { lambdaError() }, ) : MessagesNavigator { override fun navigateToEventDebugInfo(eventId: EventId?, debugInfo: TimelineItemDebugInfo) { onShowEventDebugInfoClickLambda(eventId, debugInfo) @@ -65,6 +66,10 @@ class FakeMessagesNavigator( navigateToDeveloperSettingsLambda() } + override fun navigateToCurrentLiveLocation() { + navigateToCurrentLiveLocationLambda() + } + override fun close() { closeLambda() } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 50bacb005f..65aa1d857e 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -13,6 +13,7 @@ package io.element.android.features.messages.impl import androidx.lifecycle.Lifecycle import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.PinUnpinAction +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.impl.actionlist.ActionListEvent import io.element.android.features.messages.impl.actionlist.ActionListState import io.element.android.features.messages.impl.actionlist.anActionListState @@ -120,6 +121,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds @Suppress("LargeClass") class MessagesPresenterTest { @@ -140,6 +142,39 @@ class MessagesPresenterTest { assertThat(initialState.snackbarMessage).isNull() assertThat(initialState.inviteProgress).isEqualTo(AsyncData.Uninitialized) assertThat(initialState.showReinvitePrompt).isFalse() + assertThat(initialState.showLiveLocationShareBanner).isFalse() + } + } + + @Test + fun `present - exposes live location sharing banner visibility for current room`() = runTest { + val liveLocationShareManager = FakeActiveLiveLocationShareManager( + startShareLambda = { _, _ -> Result.success(Unit) }, + ) + liveLocationShareManager.startShare(A_ROOM_ID, 60.seconds) + val presenter = createMessagesPresenter(liveLocationShareManager = liveLocationShareManager) + + presenter.testWithLifecycleOwner { + val state = consumeItemsUntilTimeout().last() + assertThat(state.showLiveLocationShareBanner).isTrue() + } + } + + @Test + fun `present - stop live location share delegates to manager for current room`() = runTest { + val stopShareLambda = lambdaRecorder> { Result.success(Unit) } + val liveLocationShareManager = FakeActiveLiveLocationShareManager( + stopShareLambda = stopShareLambda + ) + val presenter = createMessagesPresenter(liveLocationShareManager = liveLocationShareManager) + + presenter.testWithLifecycleOwner { + val state = consumeItemsUntilTimeout().last() + state.eventSink(MessagesEvent.StopLiveLocationShare) + advanceUntilIdle() + assert(stopShareLambda) + .isCalledOnce() + .with(value(A_ROOM_ID)) } } @@ -563,7 +598,7 @@ class MessagesPresenterTest { baseRoom = FakeBaseRoom( roomPermissions = roomPermissions(), ).apply { - givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1)) + givenRoomInfo(aRoomInfo(isDm = true, joinedMembersCount = 1, activeMembersCount = 1)) }, typingNoticeResult = { Result.success(Unit) }, ) @@ -1077,7 +1112,7 @@ class MessagesPresenterTest { canRedactOwn = true, canPinUnpin = true, ), - initialRoomInfo = aRoomInfo(isDirect = true, isEncrypted = true) + initialRoomInfo = aRoomInfo(isDm = true, isEncrypted = true) ).apply { givenRoomMembersState(RoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2)))) }, @@ -1347,6 +1382,7 @@ class MessagesPresenterTest { actionListEventSink: (ActionListEvent) -> Unit = {}, addRecentEmoji: AddRecentEmoji = AddRecentEmoji { _ -> lambdaError() }, markAsFullyRead: MarkAsFullyRead = FakeMarkAsFullyRead(), + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ): MessagesPresenter { return MessagesPresenter( navigator = navigator, @@ -1376,6 +1412,7 @@ class MessagesPresenterTest { featureFlagService = featureFlagService, addRecentEmoji = addRecentEmoji, markAsFullyRead = markAsFullyRead, + liveLocationShareManager = liveLocationShareManager, sessionCoroutineScope = backgroundScope, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 70ef70325e..be44c64a5a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -643,6 +643,44 @@ class MessagesViewTest { assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_message) assertNoNodeWithText(R.string.screen_room_timeline_tombstoned_room_action) } + + @Test + fun `live location banner is visible when current room is sharing`() = runAndroidComposeUiTest { + val state = aMessagesState(isCurrentlySharingLiveLocationInRoom = true) + setMessagesView(state = state) + onNodeWithText(activity!!.getString(CommonStrings.screen_room_live_location_banner)).assertExists() + } + + @Test + fun `live location banner is hidden when current room is not sharing`() = runAndroidComposeUiTest { + val state = aMessagesState(isCurrentlySharingLiveLocationInRoom = false) + setMessagesView(state = state) + onNodeWithText(activity!!.getString(CommonStrings.screen_room_live_location_banner)).assertDoesNotExist() + } + + @Test + fun `clicking stop on live location banner emits expected event`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + val state = aMessagesState( + isCurrentlySharingLiveLocationInRoom = true, + eventSink = eventsRecorder, + ) + setMessagesView(state = state) + clickOn(CommonStrings.action_stop) + eventsRecorder.assertSingle(MessagesEvent.StopLiveLocationShare) + } + + @Test + fun `clicking live location banner emit expected event`() = runAndroidComposeUiTest { + val eventsRecorder = EventsRecorder() + val state = aMessagesState( + isCurrentlySharingLiveLocationInRoom = true, + eventSink = eventsRecorder, + ) + setMessagesView(state = state) + clickOn(CommonStrings.screen_room_live_location_banner) + eventsRecorder.assertSingle(MessagesEvent.ShowLiveLocationShare) + } } private fun AndroidComposeUiTest.setMessagesView( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt index 8c7f290441..20b636081a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/actionlist/ActionListPresenterTest.kt @@ -17,6 +17,7 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser import io.element.android.features.messages.impl.fixtures.aMessageEvent import io.element.android.features.messages.impl.timeline.aTimelineItemEvent import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent @@ -1169,7 +1170,7 @@ class ActionListPresenterTest { val initialState = awaitItem() val messageEvent = aMessageEvent( isMine = true, - content = TimelineItemRtcNotificationContent(callIntent = CallIntent.VIDEO), + content = TimelineItemRtcNotificationContent(callIntent = CallIntent.VIDEO, state = RtcNotificationState.Started), ) initialState.eventSink.invoke( ActionListEvent.ComputeForMessage( diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt index 7a2cc1110a..e8d106a80f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenterTest.kt @@ -1066,7 +1066,7 @@ class MessageComposerPresenterTest { ) givenRoomInfo( aRoomInfo( - isDirect = true, + isDm = true, activeMembersCount = 2, ) ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt index 194694714b..af37fb61ef 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenterTest.kt @@ -10,6 +10,7 @@ package io.element.android.features.messages.impl.timeline import app.cash.turbine.ReceiveTurbine import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.test.FakeActiveLiveLocationShareManager import io.element.android.features.messages.impl.FakeMessagesNavigator import io.element.android.features.messages.impl.crypto.sendfailure.resolve.aResolveVerifiedUserSendFailureState import io.element.android.features.messages.impl.fixtures.aMessageEvent @@ -1012,6 +1013,7 @@ class TimelinePresenterTest { sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), timelineItemIndexer: TimelineItemIndexer = TimelineItemIndexer(), featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), + liveLocationShareManager: FakeActiveLiveLocationShareManager = FakeActiveLiveLocationShareManager(), ): TimelinePresenter { return TimelinePresenter( timelineItemsFactoryCreator = aTimelineItemsFactoryCreator(), @@ -1030,6 +1032,7 @@ class TimelinePresenterTest { roomCallStatePresenter = { aStandByCallState() }, featureFlagService = featureFlagService, analyticsService = FakeAnalyticsService(), + liveLocationShareManager = liveLocationShareManager, ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt new file mode 100644 index 0000000000..664d21ed64 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/utils/DefaultMessageSummaryFormatterTest.kt @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.utils + +import android.content.Context +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.Location +import io.element.android.features.messages.impl.timeline.model.event.RtcNotificationState +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent.Mode +import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent +import io.element.android.features.messages.impl.utils.messagesummary.DefaultMessageSummaryFormatter +import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.timeline.aProfileDetails +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +class DefaultMessageSummaryFormatterTest { + private val formatter = DefaultMessageSummaryFormatter( + RuntimeEnvironment.getApplication() as Context + ) + + @Test + @Config(qualifiers = "en") + fun `format call notification started`() { + val expected = formatter.format( + TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Started + ) + ) + assertThat(expected).isEqualTo("Call started") + } + + @Test + @Config(qualifiers = "en") + fun `format call notification declined by me`() { + val expected = formatter.format( + TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Declined(byMe = true) + ) + ) + assertThat(expected).isEqualTo("You declined a call") + } + + @Test + @Config(qualifiers = "en") + fun `format call notification declined`() { + val expected = formatter.format( + TimelineItemRtcNotificationContent( + callIntent = CallIntent.VIDEO, + state = RtcNotificationState.Declined(byMe = false) + ) + ) + assertThat(expected).isEqualTo("Call declined") + } + + @Test + @Config(qualifiers = "en") + fun `format live location`() { + val expected = formatter.format( + aLocationContent(isLive = true) + ) + assertThat(expected).isEqualTo("Shared live location") + } + + @Test + @Config(qualifiers = "en") + fun `format static location`() { + val expected = formatter.format( + aLocationContent(isLive = false) + ) + assertThat(expected).isEqualTo("Shared location") + } +} + +private fun aLocationContent(isLive: Boolean) = TimelineItemLocationContent( + senderId = A_USER_ID, + senderProfile = aProfileDetails(), + description = null, + assetType = null, + mode = if (isLive) { + Mode.Live( + lastKnownLocation = Location.fromGeoUri("geo:1,5"), + isActive = true, + endsAt = "", + endTimestamp = 0, + isOwnUser = true, + ) + } else { + Mode.Static( + location = Location.fromGeoUri("geo:1,5")!!, + ) + } +) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt index b3fb68fe05..ef27c499af 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsEvents.kt @@ -20,4 +20,5 @@ sealed interface AdvancedSettingsEvents { data class SetTheme(val theme: ThemeOption) : AdvancedSettingsEvents data class SetTimelineMediaPreviewValue(val value: MediaPreviewValue) : AdvancedSettingsEvents data class SetHideInviteAvatars(val value: Boolean) : AdvancedSettingsEvents + data class SetLiveLocationMinimumDistanceUpdate(val value: Int) : AdvancedSettingsEvents } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt index e58706e9fe..96b1cddc94 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsNode.kt @@ -10,12 +10,14 @@ package io.element.android.features.preferences.impl.advanced import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import dev.zacsweers.metro.Assisted import dev.zacsweers.metro.AssistedInject import io.element.android.annotations.ContributesNode +import io.element.android.libraries.androidutils.system.openAppSettingsPage import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) @@ -28,10 +30,12 @@ class AdvancedSettingsNode( @Composable override fun View(modifier: Modifier) { val state = presenter.present() + val context = LocalContext.current AdvancedSettingsView( state = state, modifier = modifier, - onBackClick = ::navigateUp + onBackClick = ::navigateUp, + onOpenAppSettingsClick = context::openAppSettingsPage ) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt index ae32bb01a5..3d1fb3b0c7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenter.kt @@ -25,8 +25,11 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch @Inject @@ -53,6 +56,19 @@ class AdvancedSettingsPresenter( appPreferencesStore.getThemeFlow().mapToTheme(isBlackThemeAllowed) }.collectAsState(initial = Theme.System) + @OptIn(ExperimentalCoroutinesApi::class) + val liveLocationMinimumDistanceUpdate by produceState(null) { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.LiveLocationSharing) + .flatMapLatest { isEnabled -> + if (isEnabled) { + appPreferencesStore.getLiveLocationMinimumDistanceInMetersUpdateFlow() + } else { + emptyFlow() + } + } + .collect { value = it } + } + val mediaPreviewConfigState = mediaPreviewConfigStateStore.state() val themeOption by remember { @@ -117,6 +133,9 @@ class AdvancedSettingsPresenter( } is AdvancedSettingsEvents.SetHideInviteAvatars -> mediaPreviewConfigStateStore.setHideInviteAvatars(event.value) is AdvancedSettingsEvents.SetTimelineMediaPreviewValue -> mediaPreviewConfigStateStore.setTimelineMediaPreviewValue(event.value) + is AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate -> sessionCoroutineScope.launch { + appPreferencesStore.setLiveLocationMinimumDistanceInMetersUpdate(event.value) + } is AdvancedSettingsEvents.SetCompressImages -> sessionCoroutineScope.launch { sessionPreferencesStore.setOptimizeImages(event.compress) } @@ -133,6 +152,7 @@ class AdvancedSettingsPresenter( theme = themeOption, availableThemeOptions = availableThemeOptions, mediaPreviewConfigState = mediaPreviewConfigState, + liveLocationMinimumDistanceUpdate = liveLocationMinimumDistanceUpdate, eventSink = ::handleEvent, ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt index 0525130048..94019c1f01 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsState.kt @@ -11,9 +11,9 @@ package io.element.android.features.preferences.impl.advanced import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.res.stringResource +import io.element.android.features.preferences.impl.R import io.element.android.libraries.designsystem.components.preferences.DropdownOption import io.element.android.libraries.preferences.api.store.VideoCompressionPreset -import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList data class AdvancedSettingsState( @@ -23,6 +23,7 @@ data class AdvancedSettingsState( val theme: ThemeOption, val availableThemeOptions: ImmutableList, val mediaPreviewConfigState: MediaPreviewConfigState, + val liveLocationMinimumDistanceUpdate: Int?, val eventSink: (AdvancedSettingsEvents) -> Unit ) @@ -43,24 +44,24 @@ enum class ThemeOption : DropdownOption { System { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_system) + override fun getText(): String = stringResource(R.string.theme_system) }, Light { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_light) + override fun getText(): String = stringResource(R.string.theme_light) }, Dark { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_dark) + override fun getText(): String = stringResource(R.string.theme_dark) }, Black { @Composable @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_black) + override fun getText(): String = stringResource(R.string.theme_black) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt index 87df614074..2df59e3ced 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsStateProvider.kt @@ -41,6 +41,7 @@ fun aAdvancedSettingsState( availableThemeOptions: ImmutableList = ThemeOption.entries.toImmutableList(), hideInviteAvatars: Boolean = false, timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On, + liveLocationMinimumDistanceUpdate: Int? = 50, setTimelineMediaPreviewAction: AsyncAction = AsyncAction.Uninitialized, setHideInviteAvatarsAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (AdvancedSettingsEvents) -> Unit = {}, @@ -56,5 +57,6 @@ fun aAdvancedSettingsState( setTimelineMediaPreviewAction = setTimelineMediaPreviewAction, setHideInviteAvatarsAction = setHideInviteAvatarsAction ), + liveLocationMinimumDistanceUpdate = liveLocationMinimumDistanceUpdate, eventSink = eventSink ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt index 230f5fa739..af28e3443f 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt @@ -8,15 +8,24 @@ package io.element.android.features.preferences.impl.advanced +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.SliderDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp import im.vector.app.features.analytics.plan.Interaction import io.element.android.compound.theme.ElementTheme import io.element.android.features.preferences.impl.R @@ -33,10 +42,12 @@ import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.text.stringWithLink import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListSectionHeader import io.element.android.libraries.designsystem.theme.components.ListSupportingText import io.element.android.libraries.designsystem.theme.components.ListSupportingTextDefaults +import io.element.android.libraries.designsystem.theme.components.Slider import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost @@ -47,11 +58,13 @@ import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.compose.LocalAnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction +import kotlin.math.roundToInt @Composable fun AdvancedSettingsView( state: AdvancedSettingsState, onBackClick: () -> Unit, + onOpenAppSettingsClick: () -> Unit, modifier: Modifier = Modifier, ) { val analyticsService = LocalAnalyticsService.current @@ -190,6 +203,15 @@ fun AdvancedSettingsView( } ModerationAndSafety(state) + if (state.liveLocationMinimumDistanceUpdate != null) { + LiveLocationUpdatesSection( + value = state.liveLocationMinimumDistanceUpdate, + onValueSaved = { value -> + state.eventSink(AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate(value)) + }, + onOpenAppPermissionsClick = onOpenAppSettingsClick, + ) + } } } @@ -314,6 +336,78 @@ private fun ModerationAndSafety( } } +@Composable +private fun LiveLocationUpdatesSection( + value: Int, + onValueSaved: (Int) -> Unit, + onOpenAppPermissionsClick: () -> Unit, + modifier: Modifier = Modifier, +) { + PreferenceCategory( + modifier = modifier, + showTopDivider = true, + ) { + ListSectionHeader( + title = stringResource(R.string.screen_advanced_settings_live_location_section_title), + description = { + ListSupportingText( + text = stringResource(R.string.screen_advanced_settings_live_location_section_description), + contentPadding = ListSupportingTextDefaults.Padding.None, + ) + } + ) + var sliderValue by remember(value) { mutableIntStateOf(value) } + Column( + modifier = Modifier.padding(vertical = 12.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + text = pluralStringResource( + R.plurals.screen_advanced_settings_live_location_update_distance, + sliderValue, + sliderValue, + ), + style = ElementTheme.typography.fontBodyLgRegular, + color = ElementTheme.colors.textPrimary, + ) + val valueRange = 1f..100f + val start = valueRange.start.toInt() + val end = valueRange.endInclusive.toInt() + Row(verticalAlignment = Alignment.CenterVertically) { + Text("${start}m", color = ElementTheme.colors.textSecondary, style = ElementTheme.typography.fontBodyMdRegular) + Slider( + modifier = Modifier + .weight(1f) + .padding(horizontal = 12.dp), + value = sliderValue.toFloat(), + onValueChange = { sliderValue = it.roundToInt() }, + onValueChangeFinish = { + onValueSaved(sliderValue) + }, + valueRange = valueRange, + colors = SliderDefaults.colors( + thumbColor = ElementTheme.colors.iconAccentPrimary, + activeTrackColor = ElementTheme.colors.iconAccentPrimary, + inactiveTrackColor = ElementTheme.colors.bgBadgeAccent, + inactiveTickColor = ElementTheme.colors.iconAccentPrimary, + ) + ) + Text("${end}m", color = ElementTheme.colors.textSecondary, style = ElementTheme.typography.fontBodyMdRegular) + } + } + val footerText = stringWithLink( + textRes = R.string.screen_advanced_settings_live_location_section_footer, + url = "", + linkTextRes = R.string.screen_advanced_settings_live_location_section_footer_link, + onLinkClick = { onOpenAppPermissionsClick() }, + ) + ListSupportingText( + annotatedString = footerText, + contentPadding = ListSupportingTextDefaults.Padding.Default, + ) + } +} + @PreviewWithLargeHeight @Composable internal fun AdvancedSettingsViewLightPreview(@PreviewParameter(AdvancedSettingsStateProvider::class) state: AdvancedSettingsState) = @@ -334,7 +428,8 @@ internal fun AdvancedSettingsViewBlackPreview(@PreviewParameter(AdvancedSettings private fun ContentToPreview(state: AdvancedSettingsState) { AdvancedSettingsView( state = state, - onBackClick = { } + onBackClick = { }, + onOpenAppSettingsClick = {} ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt index 9d9e80b3f3..12f13e734b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenter.kt @@ -223,7 +223,7 @@ class NotificationSettingsPresenter( notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = encryptedGroupDefaultMode != RoomNotificationMode.ALL_MESSAGES, mode = RoomNotificationMode.ALL_MESSAGES, - isOneToOne = false, + isDM = false, ) } @@ -234,7 +234,7 @@ class NotificationSettingsPresenter( notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = encryptedOneToOneDefaultMode != RoomNotificationMode.ALL_MESSAGES, mode = RoomNotificationMode.ALL_MESSAGES, - isOneToOne = true, + isDM = true, ) } }.fold( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt index 96097983c9..1357caeef3 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingNode.kt @@ -34,12 +34,12 @@ class EditDefaultNotificationSettingNode( } data class Inputs( - val isOneToOne: Boolean + val isDm: Boolean ) : NodeInputs private val callback: Callback = callback() private val inputs = inputs() - private val presenter = presenterFactory.create(inputs.isOneToOne) + private val presenter = presenterFactory.create(inputs.isDm) @Composable override fun View(modifier: Modifier) { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt index 178f7033f3..f2cb8b02cc 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingPresenter.kt @@ -42,12 +42,12 @@ import kotlin.time.Duration.Companion.seconds @AssistedInject class EditDefaultNotificationSettingPresenter( private val notificationSettingsService: NotificationSettingsService, - @Assisted private val isOneToOne: Boolean, + @Assisted private val isDm: Boolean, private val roomListService: RoomListService, ) : Presenter { @AssistedFactory interface Factory { - fun create(isOneToOne: Boolean): EditDefaultNotificationSettingPresenter + fun create(isDm: Boolean): EditDefaultNotificationSettingPresenter } private val collator = Collator.getInstance().apply { @@ -86,7 +86,7 @@ class EditDefaultNotificationSettingPresenter( } return EditDefaultNotificationSettingState( - isOneToOne = isOneToOne, + isOneToOne = isDm, mode = mode.value, roomsWithUserDefinedMode = roomsWithUserDefinedMode.value.toImmutableList(), changeNotificationSettingAction = changeNotificationSettingAction.value, @@ -96,7 +96,7 @@ class EditDefaultNotificationSettingPresenter( } private fun CoroutineScope.fetchSettings(mode: MutableState) = launch { - mode.value = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = isOneToOne).getOrThrow() + mode.value = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = isDm).getOrThrow() } @OptIn(FlowPreview::class) @@ -129,7 +129,7 @@ class EditDefaultNotificationSettingPresenter( val roomWithUserDefinedRules: Set = notificationSettingsService.getRoomsWithUserDefinedRules().getOrDefault(emptyList()).toSet() roomsWithUserDefinedMode.value = summaries .filter { roomSummary -> - roomWithUserDefinedRules.contains(roomSummary.roomId) && roomSummary.isOneToOne == isOneToOne + roomWithUserDefinedRules.contains(roomSummary.roomId) && roomSummary.isDm == isDm } .map { roomSummary -> EditNotificationSettingRoomInfo( @@ -154,9 +154,9 @@ class EditDefaultNotificationSettingPresenter( private fun CoroutineScope.setDefaultNotificationMode(mode: RoomNotificationMode, action: MutableState>) = launch { action.runUpdatingStateNoSuccess { // On modern clients, we don't have different settings for encrypted and non-encrypted rooms (Legacy clients did). - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, mode = mode, isOneToOne = isOneToOne) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, mode = mode, isDM = isDm) .map { - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, mode = mode, isOneToOne = isOneToOne) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, mode = mode, isDM = isDm) } } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt index 141adafe2b..f3faf96ba2 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt @@ -11,7 +11,6 @@ package io.element.android.features.preferences.impl.tasks import android.content.Context import coil3.SingletonImageLoader import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import io.element.android.features.invite.api.SeenInvitesStore import io.element.android.features.preferences.impl.DefaultCacheService import io.element.android.libraries.cachestore.api.CacheStore @@ -34,7 +33,7 @@ class DefaultClearCacheUseCase( private val matrixClient: MatrixClient, private val coroutineDispatchers: CoroutineDispatchers, private val defaultCacheService: DefaultCacheService, - private val okHttpClient: Provider, + private val okHttpClient: () -> OkHttpClient, private val pushService: PushService, private val seenInvitesStore: SeenInvitesStore, private val activeRoomsHolder: ActiveRoomsHolder, @@ -55,7 +54,12 @@ class DefaultClearCacheUseCase( // Clear OkHttp cache okHttpClient().cache?.delete() // Clear app cache - context.cacheDir.deleteRecursively() + context.cacheDir?.listFiles { + // But keep the logs + it.name != "logs" + }?.onEach { + it.deleteRecursively() + } // Clear some settings seenInvitesStore.clear() // Ensure any error will be displayed again diff --git a/features/preferences/impl/src/main/res/values-be/translations.xml b/features/preferences/impl/src/main/res/values-be/translations.xml index b27a22bb8d..7f487afa24 100644 --- a/features/preferences/impl/src/main/res/values-be/translations.xml +++ b/features/preferences/impl/src/main/res/values-be/translations.xml @@ -53,6 +53,9 @@ "налады сістэмы" "Сістэмныя апавяшчэнні выключаны" "Апавяшчэнні" + "Цёмная" + "Светлая" + "Сістэмная" "Выпраўленне непаладак" "Выпраўленне непаладак з апавяшчэннямі" diff --git a/features/preferences/impl/src/main/res/values-bg/translations.xml b/features/preferences/impl/src/main/res/values-bg/translations.xml index 692f0ac8f3..d5ad7facb2 100644 --- a/features/preferences/impl/src/main/res/values-bg/translations.xml +++ b/features/preferences/impl/src/main/res/values-bg/translations.xml @@ -58,6 +58,9 @@ "системни настройки" "Системните известия са изключени" "Известия" + "Тъмен" + "Светъл" + "Система" "Отстраняване на неизправности" "Отстраняване на неизправности с известията" diff --git a/features/preferences/impl/src/main/res/values-cs/translations.xml b/features/preferences/impl/src/main/res/values-cs/translations.xml index 12014e7104..e51d05c455 100644 --- a/features/preferences/impl/src/main/res/values-cs/translations.xml +++ b/features/preferences/impl/src/main/res/values-cs/translations.xml @@ -87,6 +87,9 @@ Pokud budete pokračovat, některá nastavení se mohou změnit." "systémová nastavení" "Systémová oznámení byla vypnuta" "Oznámení" + "Tmavé" + "Světlý" + "Systém" "Historie push oznámení" "Odstraňování problémů" "Odstraňování problémů s upozorněními" diff --git a/features/preferences/impl/src/main/res/values-cy/translations.xml b/features/preferences/impl/src/main/res/values-cy/translations.xml index 9711eda179..e857f6aebe 100644 --- a/features/preferences/impl/src/main/res/values-cy/translations.xml +++ b/features/preferences/impl/src/main/res/values-cy/translations.xml @@ -70,6 +70,9 @@ Os ewch ymlaen, efallai y bydd rhai o\'ch gosodiadau\'n newid." "gosodiadau system" "Hysbysiadau system wedi\'u diffodd" "Hysbysiadau" + "Tywyll" + "Golau" + "System" "Hanes gwthio" "Datrys Problemau" "Hysbysiadau datrys problemau" diff --git a/features/preferences/impl/src/main/res/values-da/translations.xml b/features/preferences/impl/src/main/res/values-da/translations.xml index 2f828a4063..459ea33632 100644 --- a/features/preferences/impl/src/main/res/values-da/translations.xml +++ b/features/preferences/impl/src/main/res/values-da/translations.xml @@ -84,6 +84,9 @@ Hvis du fortsætter, kan nogle af dine indstillinger blive ændret." "systemindstillinger" "Systemmeddelelser slået fra" "Notifikationer" + "Mørkt tema" + "Lyst tema" + "System" "Push-historik" "Fejlfind" "Fejlfinding af meddelelser" diff --git a/features/preferences/impl/src/main/res/values-de/translations.xml b/features/preferences/impl/src/main/res/values-de/translations.xml index c3722ec88c..e35cf871a1 100644 --- a/features/preferences/impl/src/main/res/values-de/translations.xml +++ b/features/preferences/impl/src/main/res/values-de/translations.xml @@ -76,6 +76,9 @@ Wenn du fortfährst, können sich einige deiner Einstellungen ändern." "Systemeinstellungen" "Systembenachrichtigungen deaktiviert" "Benachrichtigungen" + "Dunkel" + "Hell" + "System" "Verlauf pushen" "Fehlerbehebung" "Fehlerbehebung für Benachrichtigungen" diff --git a/features/preferences/impl/src/main/res/values-el/translations.xml b/features/preferences/impl/src/main/res/values-el/translations.xml index 64b651114d..6db52343d3 100644 --- a/features/preferences/impl/src/main/res/values-el/translations.xml +++ b/features/preferences/impl/src/main/res/values-el/translations.xml @@ -76,6 +76,9 @@ "ρυθμίσεις συστήματος" "Ειδοποιήσεις συστήματος ανενεργές" "Ειδοποιήσεις" + "Σκοτεινό" + "Φωτεινό" + "Σύστημα" "Ιστορικό push" "Αντιμετώπιση προβλημάτων" "Αντιμετώπιση προβλημάτων ειδοποιήσεων" diff --git a/features/preferences/impl/src/main/res/values-es/translations.xml b/features/preferences/impl/src/main/res/values-es/translations.xml index afdc23d90b..dd496a1273 100644 --- a/features/preferences/impl/src/main/res/values-es/translations.xml +++ b/features/preferences/impl/src/main/res/values-es/translations.xml @@ -63,6 +63,9 @@ Si continúas, es posible que algunos de tus ajustes cambien." "ajustes del sistema" "Notificaciones del sistema desactivadas" "Notificaciones" + "Oscuro" + "Claro" + "Sistema" "Historial de notificaciones push" "Solucionar problemas" "Solucionar problemas con las notificaciones" diff --git a/features/preferences/impl/src/main/res/values-et/translations.xml b/features/preferences/impl/src/main/res/values-et/translations.xml index 4e7ba1c26e..ba1ee2ac7c 100644 --- a/features/preferences/impl/src/main/res/values-et/translations.xml +++ b/features/preferences/impl/src/main/res/values-et/translations.xml @@ -11,6 +11,11 @@ "Peida jututubade kutsetest tunnuspildid" "Peida meedia eelvaated ajajoonel" "Katsed" + "Rakenduse seadistused" + + "Iga %1$d meeter" + "Iga %1$d meetrit" + "Sellega laadid fotosid ja videoid kiiremini üles ning vähendad andmemahtu" "Optimeeri meedia kvaliteeti" "Modereerimine ja ohutus" @@ -76,6 +81,9 @@ Kui sa jätkad muutmist, siis võivad muutuda ka need peidetud eelistused.""süsteemi seadistusi" "Süsteemi teavitused on välja lülitatud" "Teavitused" + "Tume" + "Hele" + "Süsteem" "Tõuketeadete ajalugu" "Veaotsing" "Teavituste veaotsing" diff --git a/features/preferences/impl/src/main/res/values-eu/translations.xml b/features/preferences/impl/src/main/res/values-eu/translations.xml index 42a90e0328..42416c682b 100644 --- a/features/preferences/impl/src/main/res/values-eu/translations.xml +++ b/features/preferences/impl/src/main/res/values-eu/translations.xml @@ -55,4 +55,7 @@ "sistemaren ezarpenak" "Sistemaren jakinarazpenak desaktibatuta daude" "Jakinarazpenak" + "Iluna" + "Argia" + "Sistema" diff --git a/features/preferences/impl/src/main/res/values-fa/translations.xml b/features/preferences/impl/src/main/res/values-fa/translations.xml index 05e73febb4..df42ca953c 100644 --- a/features/preferences/impl/src/main/res/values-fa/translations.xml +++ b/features/preferences/impl/src/main/res/values-fa/translations.xml @@ -19,12 +19,15 @@ "فراهم کنندهٔ آگاهی‌های ارسالی" "از کار انداختن ویرایشگر متن غنی یا نوشتن دستی مارک‌دون." "رسید‌های خواندن" + "اگر خاموش باشد، رسیدهای خوانده شدن شما برای کسی ارسال نمی‌شود. شما همچنان رسیدهای خوانده شدن را از سایر کاربران دریافت خواهید کرد." "هم‌رسانی حضور" + "اگر خاموش باشد، نمی‌توانید رسیدهای خوانده شدن یا اعلان‌های تایپ را ارسال یا دریافت کنید." "نهفتن همیشگی" "نمایش همیشگی" "در اتاق‌های خصوصی" "رسانه‌های نهفته همواره خواهند توانست با زدن رویشان نمایان شوند" "نمایش رسانه در خط زمانی" + "گزینه مشاهده منبع پیام در جدول زمانی را فعال کنید." "هیچ کاربر مسدودی ندارید" "رفع انسداد" "قادر خواهید بود دوباره همهٔ پیام‌هایش را ببینید." @@ -64,6 +67,9 @@ "تنظیمات سامانه" "آگاهی‌های سامانه‌ای خاموش شدند" "آگاهی‌ها" + "تیره" + "روشن" + "سامانه" "تاریخچهٔ آگاهی‌های ارسالی" "رفع‌اشکال" "رفع‌اشکال آگاهی‌ها" diff --git a/features/preferences/impl/src/main/res/values-fi/translations.xml b/features/preferences/impl/src/main/res/values-fi/translations.xml index f1462f3bb7..97da4e138a 100644 --- a/features/preferences/impl/src/main/res/values-fi/translations.xml +++ b/features/preferences/impl/src/main/res/values-fi/translations.xml @@ -76,6 +76,9 @@ Jos jatkat, jotkin asetukset saattavat muuttua." "järjestelmäsi asetuksia" "Järjestelmän ilmoitukset on poissa päältä" "Ilmoitukset" + "Tumma" + "Vaalea" + "Järjestelmän oletus" "Push-historia" "Vianmääritys" "Ilmoitusten vianmääritys" diff --git a/features/preferences/impl/src/main/res/values-fr/translations.xml b/features/preferences/impl/src/main/res/values-fr/translations.xml index 292b5bf9a5..3f97b67eb8 100644 --- a/features/preferences/impl/src/main/res/values-fr/translations.xml +++ b/features/preferences/impl/src/main/res/values-fr/translations.xml @@ -84,6 +84,9 @@ Si vous continuez, il est possible que certains de vos paramètres soient modifi "paramètres du système" "Les notifications du système sont désactivées" "Notifications" + "Sombre" + "Clair" + "Système" "Historique des Push" "Dépannage" "Dépanner les notifications" diff --git a/features/preferences/impl/src/main/res/values-hr/translations.xml b/features/preferences/impl/src/main/res/values-hr/translations.xml index a40a6feccd..d101146f8c 100644 --- a/features/preferences/impl/src/main/res/values-hr/translations.xml +++ b/features/preferences/impl/src/main/res/values-hr/translations.xml @@ -85,6 +85,9 @@ Ako nastavite, neke od vaših postavki mogu se promijeniti." "postavke sustava" "Obavijesti sustava su isključene" "Obavijesti" + "Tamno" + "Svijetlo" + "Sustav" "Povijest push obavijesti" "Rješavanje problema" "Rješavanje problema s obavijestima" diff --git a/features/preferences/impl/src/main/res/values-hu/translations.xml b/features/preferences/impl/src/main/res/values-hu/translations.xml index d75166df5e..4c3ff5c04d 100644 --- a/features/preferences/impl/src/main/res/values-hu/translations.xml +++ b/features/preferences/impl/src/main/res/values-hu/translations.xml @@ -84,6 +84,9 @@ Ha folytatja, egyes beállítások megváltozhatnak." "rendszerbeállításokat" "A rendszerértesítések ki vannak kapcsolva" "Értesítések" + "Sötét" + "Világos" + "Rendszer" "Leküldéses értesítések előzmények" "Hibaelhárítás" "Értesítések hibaelhárítása" diff --git a/features/preferences/impl/src/main/res/values-in/translations.xml b/features/preferences/impl/src/main/res/values-in/translations.xml index 5ce794c8ac..9c853aed45 100644 --- a/features/preferences/impl/src/main/res/values-in/translations.xml +++ b/features/preferences/impl/src/main/res/values-in/translations.xml @@ -72,6 +72,9 @@ Jika Anda melanjutkan, beberapa pengaturan Anda dapat berubah." "pengaturan sistem" "Pemberitahuan sistem dimatikan" "Notifikasi" + "Gelap" + "Terang" + "Sistem" "Riwayat dorongan" "Pemecahan masalah" "Pecahkan masalah notifikasi" diff --git a/features/preferences/impl/src/main/res/values-it/translations.xml b/features/preferences/impl/src/main/res/values-it/translations.xml index a10dcc9594..73555754fc 100644 --- a/features/preferences/impl/src/main/res/values-it/translations.xml +++ b/features/preferences/impl/src/main/res/values-it/translations.xml @@ -11,6 +11,14 @@ "Nascondi gli avatar nelle richieste di invito alle stanze" "Nascondi le anteprime dei media nelle conversazioni" "Labs" + "La distanza che devi percorrere per attivare un aggiornamento." + "Assicurati che l\'opzione \"Posizione precisa\" sia abilitata per questa app. Per modificare l\'autorizzazione, vai in %1$s." + "Impostazioni app" + "Aggiornamenti posizione in tempo reale" + + "Ogni %1$d metro" + "Ogni %1$d metri" + "Carica foto e video più velocemente e riduci l\'utilizzo dei dati" "Ottimizza la qualità dei contenuti multimediali" "Moderazione e Sicurezza" @@ -76,6 +84,9 @@ Se procedi, alcune delle tue impostazioni potrebbero cambiare." "impostazioni di sistema" "Notifiche di sistema disattivate" "Notifiche" + "Scuro" + "Chiaro" + "Sistema" "Cronologia push" "Risoluzione dei problemi" "Risoluzione di problemi delle notifiche" diff --git a/features/preferences/impl/src/main/res/values-ja/translations.xml b/features/preferences/impl/src/main/res/values-ja/translations.xml index 22334c4120..95380cf148 100644 --- a/features/preferences/impl/src/main/res/values-ja/translations.xml +++ b/features/preferences/impl/src/main/res/values-ja/translations.xml @@ -83,6 +83,9 @@ "システム設定" "システムで通知がオフです" "通知" + "ダーク" + "ライト" + "システム" "プッシュ履歴" "トラブルシューティング" "通知のトラブルシューティング" diff --git a/features/preferences/impl/src/main/res/values-ka/translations.xml b/features/preferences/impl/src/main/res/values-ka/translations.xml index 1efe197267..5a20e718a0 100644 --- a/features/preferences/impl/src/main/res/values-ka/translations.xml +++ b/features/preferences/impl/src/main/res/values-ka/translations.xml @@ -50,6 +50,9 @@ "სისტემის პარამეტრები" "სისტემის შეტყობინებები გამორთულია" "შეტყობინებები" + "მუქი" + "ღია" + "სისტემა" "პრობლემების გადაჭრა" "პრობლემების გადაჭრის შეტყობინებები" diff --git a/features/preferences/impl/src/main/res/values-ko/translations.xml b/features/preferences/impl/src/main/res/values-ko/translations.xml index 5e17d57a87..e2c5e8e83b 100644 --- a/features/preferences/impl/src/main/res/values-ko/translations.xml +++ b/features/preferences/impl/src/main/res/values-ko/translations.xml @@ -77,6 +77,9 @@ "시스템 설정" "시스템 알림이 꺼져 있습니다." "알림" + "다크" + "라이트" + "시스템" "푸시 기록" "문제 해결" "문제 해결 알림" diff --git a/features/preferences/impl/src/main/res/values-nb/translations.xml b/features/preferences/impl/src/main/res/values-nb/translations.xml index 90ec12a1a1..ac67e04259 100644 --- a/features/preferences/impl/src/main/res/values-nb/translations.xml +++ b/features/preferences/impl/src/main/res/values-nb/translations.xml @@ -76,6 +76,9 @@ Hvis du fortsetter, kan noen av innstillingene dine endres." "systeminnstillinger" "Systemvarsler er slått av" "Varslinger" + "Mørk" + "Lys" + "System" "Push-historikk" "Feilsøk" "Feilsøk varsler" diff --git a/features/preferences/impl/src/main/res/values-nl/translations.xml b/features/preferences/impl/src/main/res/values-nl/translations.xml index 28614965c5..c5c439a0c3 100644 --- a/features/preferences/impl/src/main/res/values-nl/translations.xml +++ b/features/preferences/impl/src/main/res/values-nl/translations.xml @@ -54,6 +54,9 @@ Als je doorgaat, kunnen sommige van je instellingen veranderen." "systeeminstellingen" "Systeemmeldingen uitgeschakeld" "Meldingen" + "Donker" + "Licht" + "Systeem" "Problemen oplossen" "Problemen met meldingen oplossen" diff --git a/features/preferences/impl/src/main/res/values-pl/translations.xml b/features/preferences/impl/src/main/res/values-pl/translations.xml index 9e2c56e580..3fc2a3eac8 100644 --- a/features/preferences/impl/src/main/res/values-pl/translations.xml +++ b/features/preferences/impl/src/main/res/values-pl/translations.xml @@ -11,6 +11,15 @@ "Ukryj awatary w prośbach o dołączenie do pokoju" "Ukryj podglądy multimediów na osi czasu" "Laboratoria" + "Odległość, jaką należy pokonać, aby uruchomić aktualizację." + "Upewnij się, że \"Dokładna lokalizacja\" jest włączona dla tej aplikacji. Aby zmienić to uprawnienie, przejdź do %1$s." + "Ustawienia aplikacji" + "Aktualizacje lokalizacji na żywo" + + "Co %1$d metr" + "Co %1$d metry" + "Co %1$d metrów" + "Przesyłaj zdjęcia i filmy szybciej, zmniejszając zużycie danych" "Optymalizuj jakość multimediów" "Moderacja i bezpieczeństwo" @@ -76,6 +85,9 @@ Niektóre ustawienia mogą ulec zmianie, jeśli kontynuujesz." "ustawienia systemowe" "Powiadomienia systemowe wyłączone" "Powiadomienia" + "Ciemny" + "Jasny" + "System" "Historia powiadomień Push" "Rozwiązywanie problemów" "Rozwiązywanie problemów powiadomień" diff --git a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml index f6e1bc90ba..be354681f5 100644 --- a/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/preferences/impl/src/main/res/values-pt-rBR/translations.xml @@ -76,6 +76,9 @@ Se você continuar, algumas de suas configurações poderão mudar." "configurações do seu sistema" "Notificações do sistema desativadas" "Notificações" + "Escuro" + "Claro" + "Sistema" "Histórico de push" "Solução de problemas" "Solucionar problemas de notificações" diff --git a/features/preferences/impl/src/main/res/values-pt/translations.xml b/features/preferences/impl/src/main/res/values-pt/translations.xml index ffd38b961f..0e27d58de5 100644 --- a/features/preferences/impl/src/main/res/values-pt/translations.xml +++ b/features/preferences/impl/src/main/res/values-pt/translations.xml @@ -76,6 +76,9 @@ Se prosseguires, algumas delas podem ser alteradas." "configurações do sistema" "Notificações do sistema desativadas" "Notificações" + "Escuro" + "Claro" + "Sistema" "Histórico de push" "Resolução de problemas" "Corrigir notificações" diff --git a/features/preferences/impl/src/main/res/values-ro/translations.xml b/features/preferences/impl/src/main/res/values-ro/translations.xml index 6f8e41c5b9..18f8326bf3 100644 --- a/features/preferences/impl/src/main/res/values-ro/translations.xml +++ b/features/preferences/impl/src/main/res/values-ro/translations.xml @@ -78,6 +78,9 @@ Dacă continuați, unele dintre setările dumneavoastră pot fi modificate.""Setări de sistem" "Notificările de sistem sunt dezactivate" "Notificări" + "Întunecat" + "Deschis" + "Sistem" "Istoricul notificărilor" "Depanare" "Depanați notificările" diff --git a/features/preferences/impl/src/main/res/values-ru/translations.xml b/features/preferences/impl/src/main/res/values-ru/translations.xml index 77be6fd8db..edb98feee8 100644 --- a/features/preferences/impl/src/main/res/values-ru/translations.xml +++ b/features/preferences/impl/src/main/res/values-ru/translations.xml @@ -76,6 +76,9 @@ "системные настройки" "Системные уведомления выключены" "Уведомления" + "Темная" + "Светлое" + "Системное" "История уведомлений" "Устранение неполадок" "Уведомления об устранении неполадок" diff --git a/features/preferences/impl/src/main/res/values-sk/translations.xml b/features/preferences/impl/src/main/res/values-sk/translations.xml index 9968c6d4cb..530fccd90b 100644 --- a/features/preferences/impl/src/main/res/values-sk/translations.xml +++ b/features/preferences/impl/src/main/res/values-sk/translations.xml @@ -78,6 +78,9 @@ Ak budete pokračovať, niektoré z vašich nastavení sa môžu zmeniť.""nastavenia systému" "Systémové oznámenia sú vypnuté" "Oznámenia" + "Tmavý" + "Svetlý" + "Systém" "História push oznámení" "Riešenie problémov" "Oznámenia riešení problémov" diff --git a/features/preferences/impl/src/main/res/values-sv/translations.xml b/features/preferences/impl/src/main/res/values-sv/translations.xml index e25e36a44f..109000440f 100644 --- a/features/preferences/impl/src/main/res/values-sv/translations.xml +++ b/features/preferences/impl/src/main/res/values-sv/translations.xml @@ -70,6 +70,9 @@ Om du fortsätter kan vissa av dina inställningar ändras." "systeminställningar" "Systemaviseringar avstängda" "Aviseringar" + "Mörkt" + "Ljust" + "System" "Push-historik" "Felsök" "Felsök aviseringar" diff --git a/features/preferences/impl/src/main/res/values-tr/translations.xml b/features/preferences/impl/src/main/res/values-tr/translations.xml index 0df8500fda..78e9018554 100644 --- a/features/preferences/impl/src/main/res/values-tr/translations.xml +++ b/features/preferences/impl/src/main/res/values-tr/translations.xml @@ -74,6 +74,9 @@ Devam ederseniz, bazı ayarlarınız değişebilir." "si̇stem ayarları" "Sistem bildirimleri kapalı" "Bildirimler" + "Koyu" + "Aydınlık" + "Sistem" "Sorun gider" "Sorun Giderme Bildirimleri" diff --git a/features/preferences/impl/src/main/res/values-uk/translations.xml b/features/preferences/impl/src/main/res/values-uk/translations.xml index d145724af8..4d8d738122 100644 --- a/features/preferences/impl/src/main/res/values-uk/translations.xml +++ b/features/preferences/impl/src/main/res/values-uk/translations.xml @@ -11,6 +11,15 @@ "Сховати аватари у запитах на запрошення до кімнат" "Сховати попередній перегляд медіа у стрічці" "Лабораторії" + "Відстань, яку потрібно пройти, щоб ініціювати оновлення." + "Переконайтеся, що для цього додатка увімкнено функцію «Точна геолокація». Щоб змінити дозвіл, перейдіть на сторінку %1$s." + "Налаштування додатка" + "Оновлення місцезнаходження в реальному часі" + + "Кожен %1$d метр" + "Кожні %1$d метри" + "Кожні %1$d метрів" + "Швидше завантажуйте фотографії та відео та зменшуйте використання даних" "Оптимізуйте медіаякість" "Модерування й безпека" @@ -76,6 +85,9 @@ "системні налаштування" "Системні сповіщення вимкнені" "Сповіщення" + "Темна" + "Світла" + "Системна" "Історія push-сповіщень" "Усунення несправностей" "Усунення неполадок сповіщень" diff --git a/features/preferences/impl/src/main/res/values-ur/translations.xml b/features/preferences/impl/src/main/res/values-ur/translations.xml index 470763e877..35b8f4aa4e 100644 --- a/features/preferences/impl/src/main/res/values-ur/translations.xml +++ b/features/preferences/impl/src/main/res/values-ur/translations.xml @@ -53,6 +53,9 @@ "نظام کی ترتیبات" "نظام کی اطلاعات بند کر دی گئیں" "اطلاعات" + "اندھیرا" + "روشنی" + "نظام" "ازالہ کریں" "اطلاعات کا ازالہ کریں" diff --git a/features/preferences/impl/src/main/res/values-uz/translations.xml b/features/preferences/impl/src/main/res/values-uz/translations.xml index 9c81fc3daa..884027f9b8 100644 --- a/features/preferences/impl/src/main/res/values-uz/translations.xml +++ b/features/preferences/impl/src/main/res/values-uz/translations.xml @@ -76,6 +76,9 @@ Davom ettirsangiz, baʼzi sozlamalaringiz oʻzgarishi mumkin." "tizim sozlamalari" "Tizim bildirishnomalari o\'chirilgan" "Bildirishnomalar" + "Tungi" + "Nur" + "Tizim" "Bildirishnoma tarixi" "Muammolarni bartaraf etish" "Bildirishnomalar bilan bog‘liq muammolarni bartaraf etish" diff --git a/features/preferences/impl/src/main/res/values-vi/translations.xml b/features/preferences/impl/src/main/res/values-vi/translations.xml index 9f24244b7e..9889b1697a 100644 --- a/features/preferences/impl/src/main/res/values-vi/translations.xml +++ b/features/preferences/impl/src/main/res/values-vi/translations.xml @@ -61,6 +61,9 @@ Nếu bạn tiếp tục, một số cài đặt của bạn có thể thay đ "cài đặt hệ thống" "Thông báo hệ thống đã tắt" "Thông báo" + "Tối" + "Sáng" + "Hệ thống" "Khắc phục sự cố" "Khắc phục sự cố thông báo" diff --git a/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml b/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml index 634911100a..03892ce980 100644 --- a/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh-rTW/translations.xml @@ -76,6 +76,9 @@ "系統設定" "已關閉系統通知" "通知" + "深色" + "淺色" + "系統" "推播通知歷史紀錄" "疑難排解" "疑難排解通知" diff --git a/features/preferences/impl/src/main/res/values-zh/translations.xml b/features/preferences/impl/src/main/res/values-zh/translations.xml index 41eb147141..e91bc58752 100644 --- a/features/preferences/impl/src/main/res/values-zh/translations.xml +++ b/features/preferences/impl/src/main/res/values-zh/translations.xml @@ -83,6 +83,9 @@ "系统设置" "系统通知已关闭" "通知" + "深色" + "浅色" + "系统" "推送历史" "排查问题" "排查通知问题" diff --git a/features/preferences/impl/src/main/res/values/localazy.xml b/features/preferences/impl/src/main/res/values/localazy.xml index d5abe1df6a..a431139fd6 100644 --- a/features/preferences/impl/src/main/res/values/localazy.xml +++ b/features/preferences/impl/src/main/res/values/localazy.xml @@ -84,6 +84,10 @@ If you proceed, some of your settings may change." "system settings" "System notifications turned off" "Notifications" + "Black" + "Dark" + "Light" + "System" "Push history" "Troubleshoot" "Troubleshoot notifications" diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt index fe121e4fe9..27d91bd8de 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsPresenterTest.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.media.MediaPreviewValue +import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.preferences.api.store.VideoCompressionPreset import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore @@ -209,6 +210,72 @@ class AdvancedSettingsPresenterTest { } } + @Test + fun `present - live location minimum distance is null when feature is disabled`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore( + liveLocationMinimumDistanceUpdate = 50, + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.LiveLocationSharing, false) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isNull() + } + } + } + + @Test + fun `present - exposes live location minimum distance from app preferences`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore( + liveLocationMinimumDistanceUpdate = 50, + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isEqualTo(50) + } + } + } + + @Test + fun `present - saving live location minimum distance updates app preferences`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore( + liveLocationMinimumDistanceUpdate = 10, + ) + val featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.LiveLocationSharing, true) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore, featureFlagService = featureFlagService) + + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isEqualTo(10) + eventSink(AdvancedSettingsEvents.SetLiveLocationMinimumDistanceUpdate(42)) + } + with(awaitItem()) { + assertThat(liveLocationMinimumDistanceUpdate).isEqualTo(42) + } + } + } + @Test fun `present - black theme option shown when feature flag enabled`() = runTest { val presenter = createAdvancedSettingsPresenter( @@ -338,7 +405,7 @@ class AdvancedSettingsPresenterTest { } private fun CoroutineScope.createAdvancedSettingsPresenter( - appPreferencesStore: InMemoryAppPreferencesStore = InMemoryAppPreferencesStore(), + appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(), sessionPreferencesStore: InMemorySessionPreferencesStore = InMemorySessionPreferencesStore(), mediaPreviewConfigStateStore: MediaPreviewConfigStateStore = FakeMediaPreviewConfigStateStore(), featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt index b6fe5c3d0b..302a209578 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsViewTest.kt @@ -62,7 +62,7 @@ class AdvancedSettingsViewTest { ), ) clickOn(CommonStrings.common_appearance) - clickOn(CommonStrings.common_dark) + clickOn(R.string.theme_dark) eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTheme(ThemeOption.Dark)) } @@ -75,7 +75,7 @@ class AdvancedSettingsViewTest { ) clickOn(CommonStrings.common_appearance) run { - val text = activity!!.getString(CommonStrings.common_black) + val text = activity!!.getString(R.string.theme_black) onNodeWithText(text).assertExists() } } @@ -88,7 +88,7 @@ class AdvancedSettingsViewTest { ), ) clickOn(CommonStrings.common_appearance) - assertNoNodeWithText(CommonStrings.common_black) + assertNoNodeWithText(R.string.theme_black) } @Test @@ -250,6 +250,7 @@ private fun AndroidComposeUiTest.setAdvancedSettingsView( state: AdvancedSettingsState, analyticsService: AnalyticsService = FakeAnalyticsService(), onBackClick: () -> Unit = EnsureNeverCalled(), + onOpenAppSettings: () -> Unit = EnsureNeverCalled(), ) { setContent { CompositionLocalProvider( @@ -258,6 +259,7 @@ private fun AndroidComposeUiTest.setAdvancedSettingsView( AdvancedSettingsView( state = state, onBackClick = onBackClick, + onOpenAppSettingsClick = onOpenAppSettings ) } } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt index e03b65f0a9..509d00db25 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/EditDefaultNotificationSettingsPresenterTest.kt @@ -198,7 +198,7 @@ class EditDefaultNotificationSettingsPresenterTest { ): EditDefaultNotificationSettingPresenter { return EditDefaultNotificationSettingPresenter( notificationSettingsService = notificationSettingsService, - isOneToOne = false, + isDm = false, roomListService = roomListService, ) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt index 9b36c477a4..26bb0ba1ee 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTest.kt @@ -61,8 +61,8 @@ class NotificationSettingsPresenterTest { val notificationSettingsService = FakeNotificationSettingsService() val presenter = createNotificationSettingsPresenter(notificationSettingsService) presenter.test { - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES) - notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false, mode = RoomNotificationMode.ALL_MESSAGES) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = true, isDM = false, mode = RoomNotificationMode.ALL_MESSAGES) + notificationSettingsService.setDefaultRoomNotificationMode(isEncrypted = false, isDM = false, mode = RoomNotificationMode.ALL_MESSAGES) val updatedState = consumeItemsUntilPredicate { (it.matrixSettings as? NotificationSettingsState.MatrixSettings.Valid) ?.defaultGroupNotificationMode == RoomNotificationMode.ALL_MESSAGES @@ -79,12 +79,12 @@ class NotificationSettingsPresenterTest { presenter.test { notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = true, - isOneToOne = false, + isDM = false, mode = RoomNotificationMode.ALL_MESSAGES ) notificationSettingsService.setDefaultRoomNotificationMode( isEncrypted = false, - isOneToOne = false, + isDM = false, mode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ) val updatedState = consumeItemsUntilPredicate { diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt index b4e7faa01e..2568a6fba9 100755 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt @@ -14,7 +14,6 @@ import androidx.core.net.toFile import androidx.core.net.toUri import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import dev.zacsweers.metro.SingleIn import io.element.android.appconfig.RageshakeConfig import io.element.android.features.rageshake.api.logs.createWriteToFilesConfiguration @@ -77,7 +76,7 @@ class DefaultBugReporter( private val screenshotHolder: ScreenshotHolder, private val crashDataStore: CrashDataStore, private val coroutineDispatchers: CoroutineDispatchers, - private val okHttpClient: Provider, + private val okHttpClient: () -> OkHttpClient, private val userAgentProvider: UserAgentProvider, private val sessionStore: SessionStore, private val buildMeta: BuildMeta, diff --git a/features/rageshake/impl/src/main/res/values-fa/translations.xml b/features/rageshake/impl/src/main/res/values-fa/translations.xml index ba5ab756db..2e27f97ba6 100644 --- a/features/rageshake/impl/src/main/res/values-fa/translations.xml +++ b/features/rageshake/impl/src/main/res/values-fa/translations.xml @@ -7,6 +7,7 @@ "لطفاً مشکل را شرح دهید. چه‌کار کردید؟ انتظار داشتید چه بشود؟ ولی چه شد؟ لطفاً‌تا جای ممکن وارد جزییات شوید." "شرح مشکل…" "ترجیحاً توضیحات را به زبان انگلیسی بنویسید." + "توضیحات خیلی کوتاه است، لطفاً جزئیات بیشتری در مورد آنچه اتفاق افتاده ارائه دهید. متشکرم!" "ارسال رخدادنگارهای خطا" "اجازه به گزارش‌ها" "ارسال تصویر صفحه" diff --git a/features/rageshake/impl/src/main/res/values-uk/translations.xml b/features/rageshake/impl/src/main/res/values-uk/translations.xml index 3999133537..c29306b9bf 100644 --- a/features/rageshake/impl/src/main/res/values-uk/translations.xml +++ b/features/rageshake/impl/src/main/res/values-uk/translations.xml @@ -14,5 +14,7 @@ "Надіслати знімок екрана" "Журнали будуть додані до вашого повідомлення, щоб переконатися, що все працює належним чином. Щоб надіслати повідомлення без журналів, вимкніть це налаштування." "Стався збій %1$s під час останнього користування. Хочете поділитися з нами звітом про збій?" + "Якщо у вас виникають проблеми зі сповіщеннями, надсилання нам правил push-сповіщень допоможе нам визначити першопричину. Зверніть увагу, що ці правила можуть містити приватну інформацію, таку як ваше ім’я користувача або ключові слова, за якими ви отримували сповіщення." + "Налаштування сповіщень" "Переглянути журнали" diff --git a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml index 2bd79bddd2..4bcb764219 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-fa/translations.xml @@ -1,14 +1,14 @@ - "فقط مدیران" + "ادمین" "تحریم افراد" - "برداشتن پیام‌ها" - "هرکسی" - "دعوت افراد و پذیرش درخواست‌های پیوستن" - "نظارت اعضا" + "حذف پیام‌ها" + "عضو" + "دعوت کاربران" + "مدیریت اعضا" "پیام‌ها و محتوا" - "مدیرن و ناظران" - "برداشتن افراد و رد درخواست‌های پیوستن" + "ناظم" + "حذف افراد" "تغییر چهرک اتاق" "ویرایش جزییات" "تغییر نام اتاق" @@ -44,8 +44,8 @@ "تحریم نکردن از اتاق" "محروم" "اعضا" - "فقط مدیران" - "مدیرن و ناظران" + "ادمین" + "ناظم" "مالک" "اعضای اتاق" "رفع تحریم %1$s" @@ -62,5 +62,5 @@ "بازنشانی اجازه‌ها؟" "نقش‌ها" "جزییات اتاق" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" diff --git a/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml index e44a1dba21..9c88a2f20e 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-hu/translations.xml @@ -6,6 +6,7 @@ "Üzenetek eltávolítása" "Tag" "Emberek meghívása" + "Valós idejű hely megosztása" "Tér kezelése" "Szobák kezelése" "Tagok kezelése" diff --git a/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml index b1dea12151..ac1366d988 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-it/translations.xml @@ -6,6 +6,7 @@ "Rimuovi messaggi" "Membro" "Invita persone" + "Condividi posizione in tempo reale" "Gestire lo spazio" "Gestisci le stanze" "Gestisci membri" diff --git a/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml index 44659c47cd..9b570f5261 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-pl/translations.xml @@ -1,17 +1,24 @@ - "Tylko administratorzy" + "Administrator" "Banowanie osób" + "Zmień ustawienia" "Usuń wiadomości" - "Zapraszanie osób i akceptowanie próśb o dołączenie" + "Członek" + "Zaproś osoby" + "Udostępnij lokalizację na żywo" + "Zarządzaj przestrzeniami" + "Zarządzaj pokojami" + "Zarządzaj członkami" "Wiadomości i zawartość" - "Administratorzy i moderatorzy" - "Usuwanie osób i odrzucanie próśb o dołączenie" + "Moderator" + "Usuń osoby" "Zmień awatar pokoju" - "Edytuj pokój" + "Edytuj szczegóły" "Zmień nazwę pokoju" "Zmień temat pokoju" "Wysyłanie wiadomości" + "Uprawnienia" "Edytuj administratorów" "Tej akcji nie będzie można cofnąć. Promujesz użytkownika, który będzie posiadał takie same uprawnienia jak Ty." "Dodać administratora?" @@ -21,7 +28,7 @@ "Nie będzie można cofnąć tej zmiany, jeśli się zdegradujesz. Jeśli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju, nie będziesz w stanie odzyskać uprawnień." "Zdegradować siebie?" "%1$s (Oczekujące)" - "(Oczekujący)" + "(Oczekujące)" "Administratorzy automatycznie mają uprawnienia moderatora" "Właściciele automatycznie mają uprawnienia administratora." "Edytuj moderatorów" @@ -31,7 +38,14 @@ "Członków" "Masz niezapisane zmiany." "Zapisać zmiany?" - "W tym pokoju nie ma zbanowanych użytkowników." + "Nie ma zbanowanych użytkowników." + + "%1$d zbanowany" + "%1$d zbanowanych" + "%1$d zbanowanych" + + "Sprawdź pisownię lub wyszukaj ponownie" + "Brak wyników dla “%1$s”" "%1$d osoba" "%1$d osoby" @@ -44,8 +58,14 @@ "Odbanuj z pokoju" "Zbanowanych" "Członków" - "Tylko administratorzy" - "Administratorzy i moderatorzy" + + "%1$d zaproszony" + "%1$d zaproszonych" + "%1$d zaproszonych" + + "Oczekuje" + "Administrator" + "Moderator" "Właściciel" "Członkowie pokoju" "Odbanowanie %1$s" @@ -58,10 +78,12 @@ "Wiadomości i zawartość" "Moderatorzy" "Właściciele" - "Resetuj uprawnienia" + "Uprawnienia" + "Zresetuj uprawnienia" "Po zresetowaniu uprawnień utracisz bieżące ustawienia." "Zresetować uprawnienia?" "Role" "Szczegóły pokoju" + "Szczegóły przestrzeni" "Role i uprawnienia" diff --git a/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml index 7ce3e78387..99f21bb403 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-uk/translations.xml @@ -38,6 +38,11 @@ "У вас є не збережені зміни." "Зберегти зміни?" "Немає заблокованих користувачів." + + "%1$d Заблокований" + "%1$d Заблоковано" + "%1$d Заблоковано" + "Перевірте правопис або спробуйте новий пошук" "Немає результатів за запитом «%1$s»" diff --git a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml index b28cf8e524..53edd50a6d 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-zh/translations.xml @@ -6,6 +6,7 @@ "移除消息" "成员" "邀请人员" + "共享实时位置" "管理空间" "管理房间" "管理成员" diff --git a/features/rolesandpermissions/impl/src/main/res/values/localazy.xml b/features/rolesandpermissions/impl/src/main/res/values/localazy.xml index e5ab3f1cd7..dc89095786 100644 --- a/features/rolesandpermissions/impl/src/main/res/values/localazy.xml +++ b/features/rolesandpermissions/impl/src/main/res/values/localazy.xml @@ -6,6 +6,7 @@ "Remove messages" "Member" "Invite people" + "Share live location" "Manage space" "Manage rooms" "Manage members" diff --git a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt index 3d863321e3..15e320c8f8 100644 --- a/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt +++ b/features/roomcall/impl/src/main/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenter.kt @@ -23,7 +23,6 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.notification.CallIntent import io.element.android.libraries.matrix.api.room.CallIntentConsensus import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.canCall import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState diff --git a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt index 4c6fcf8e59..0612adbea1 100644 --- a/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt +++ b/features/roomcall/impl/src/test/kotlin/io/element/android/features/roomcall/impl/RoomCallStatePresenterTest.kt @@ -89,10 +89,10 @@ class RoomCallStatePresenterTest { } @Test - fun `present - initial state - when is direct room`() = runTest { + fun `present - initial state - when is DM room`() = runTest { val room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - initialRoomInfo = aRoomInfo(isDirect = true), + initialRoomInfo = aRoomInfo(isDm = true), roomPermissions = roomPermissions(true), ) ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt index 5fd44076e6..167cc2ced5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenter.kt @@ -35,26 +35,21 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.encryption.identity.IdentityState import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMember -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState import io.element.android.libraries.matrix.api.room.roomNotificationSettings -import io.element.android.libraries.matrix.ui.room.getCurrentRoomMember import io.element.android.libraries.matrix.ui.room.getDirectRoomMember import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange import io.element.android.libraries.preferences.api.store.AppPreferencesStore import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.api.AnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction -import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -64,7 +59,6 @@ import kotlinx.coroutines.launch class RoomDetailsPresenter( private val client: MatrixClient, private val room: JoinedRoom, - private val featureFlagService: FeatureFlagService, private val notificationSettingsService: NotificationSettingsService, private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory, private val leaveRoomPresenter: Presenter, @@ -99,9 +93,8 @@ class RoomDetailsPresenter( val canonicalAlias by remember { derivedStateOf { roomInfo.canonicalAlias } } val isEncrypted by remember { derivedStateOf { roomInfo.isEncrypted == true } } val dmMember by room.getDirectRoomMember(membersState) - val currentMember by room.getCurrentRoomMember(membersState) val roomMemberDetailsPresenter = roomMemberDetailsPresenter(dmMember) - val roomType = getRoomType(dmMember, currentMember) + val roomType = getRoomType(dmMember) val roomCallState = roomCallStatePresenter.present() val joinedMemberCount by remember { derivedStateOf { roomInfo.joinedMembersCount } } @@ -114,14 +107,11 @@ class RoomDetailsPresenter( } } - val isKnockRequestsEnabled by remember { - featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock) - }.collectAsState(false) val knockRequestsCount by produceState(null) { room.knockRequestsFlow.collect { value = it.size } } val canShowKnockRequests by remember { - derivedStateOf { isKnockRequestsEnabled && permissions.knockRequestsPermissions.hasAny && joinRule == JoinRule.Knock } + derivedStateOf { permissions.knockRequestsPermissions.hasAny && joinRule == JoinRule.Knock } } val canShowSecurityAndPrivacy by remember { derivedStateOf { !isDm && permissions.securityAndPrivacyPermissions.hasAny(isSpace = false, joinRule = joinRule) } @@ -147,7 +137,7 @@ class RoomDetailsPresenter( } RoomDetailsEvent.UnmuteNotification -> { scope.launch(dispatchers.io) { - notificationSettingsService.unmuteRoom(room.roomId, isEncrypted, room.isOneToOne) + notificationSettingsService.unmuteRoom(room.roomId, isEncrypted, room.isDm()) } } is RoomDetailsEvent.SetFavorite -> scope.setFavorite(event.isFavorite) @@ -186,7 +176,7 @@ class RoomDetailsPresenter( isFavorite = isFavorite, displayRolesAndPermissionsSettings = !isDm && permissions.canEditRolesAndPermissions, isPublic = joinRule == JoinRule.Public, - heroes = roomInfo.heroes.toImmutableList(), + heroes = roomInfo.heroes, pinnedMessagesCount = pinnedMessagesCount, snackbarMessage = snackbarMessage, canShowKnockRequests = canShowKnockRequests, @@ -210,15 +200,9 @@ class RoomDetailsPresenter( } @Composable - private fun getRoomType( - dmMember: RoomMember?, - currentMember: RoomMember?, - ): RoomDetailsType = remember(dmMember, currentMember) { - if (dmMember != null && currentMember != null) { - RoomDetailsType.Dm( - me = currentMember, - otherMember = dmMember, - ) + private fun getRoomType(dmMember: RoomMember?): RoomDetailsType = remember(dmMember) { + if (dmMember != null) { + RoomDetailsType.Dm(otherMember = dmMember) } else { RoomDetailsType.Room } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt index e74f71322d..90a912e86f 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsState.kt @@ -77,10 +77,7 @@ data class RoomDetailsState( @Immutable sealed interface RoomDetailsType { data object Room : RoomDetailsType - data class Dm( - val me: RoomMember, - val otherMember: RoomMember, - ) : RoomDetailsType + data class Dm(val otherMember: RoomMember) : RoomDetailsType } @Immutable diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index 7f3701a770..ad627d8677 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -13,7 +13,6 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.aStandByCallState -import io.element.android.features.roomdetails.impl.members.aRoomMember import io.element.android.features.userprofile.api.UserProfileState import io.element.android.features.userprofile.api.UserProfileVerificationState import io.element.android.features.userprofile.shared.aUserProfileState @@ -75,6 +74,7 @@ fun aDmRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -84,7 +84,8 @@ fun aDmRoomMember( powerLevel = powerLevel, isIgnored = isIgnored, role = role, - membershipChangeReason = membershipChangeReason + membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomDetailsState( @@ -179,10 +180,7 @@ fun aDmRoomDetailsState( roomName = roomName, isPublic = false, isEncrypted = isEncrypted, - roomType = RoomDetailsType.Dm( - me = aRoomMember(), - otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored), - ), + roomType = RoomDetailsType.Dm(otherMember = aDmRoomMember(isIgnored = isDmMemberIgnored)), roomMemberDetailsState = aUserProfileState( isBlocked = AsyncData.Success(isDmMemberIgnored), verificationState = dmRoomMemberVerificationState, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index c48716db11..e877c24554 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -31,6 +32,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign @@ -52,7 +54,6 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarType -import io.element.android.libraries.designsystem.components.avatar.DmAvatars import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.MainActionButton import io.element.android.libraries.designsystem.components.list.ListItemContent @@ -91,6 +92,7 @@ import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.analytics.compose.LocalAnalyticsService import io.element.android.services.analyticsproviders.api.trackers.captureInteraction import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @Composable @@ -154,9 +156,9 @@ fun RoomDetailsView( } is RoomDetailsType.Dm -> { DmHeaderSection( - me = state.roomType.me, otherMember = state.roomType.otherMember, roomName = state.roomName, + isTombstoned = state.isTombstoned, openAvatarPreview = { name, avatarUrl -> openAvatarPreview(name, avatarUrl) }, @@ -417,6 +419,7 @@ private fun RoomHeaderSection( ), contentDescription = stringResource(CommonStrings.a11y_room_avatar), modifier = Modifier + .clip(CircleShape) .clickable( enabled = avatarUrl != null, onClickLabel = stringResource(CommonStrings.action_view), @@ -435,9 +438,9 @@ private fun RoomHeaderSection( @Composable private fun DmHeaderSection( - me: RoomMember, otherMember: RoomMember, roomName: String, + isTombstoned: Boolean, openAvatarPreview: (name: String, url: String) -> Unit, onSubtitleClick: (String) -> Unit, modifier: Modifier = Modifier @@ -448,11 +451,24 @@ private fun DmHeaderSection( .padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - DmAvatars( - userAvatarData = me.getAvatarData(size = AvatarSize.DmCluster), - otherUserAvatarData = otherMember.getAvatarData(size = AvatarSize.DmCluster), - openAvatarPreview = { url -> openAvatarPreview(me.getBestName(), url) }, - openOtherAvatarPreview = { url -> openAvatarPreview(roomName, url) }, + Avatar( + avatarData = AvatarData(otherMember.userId.value, roomName, otherMember.avatarUrl, AvatarSize.RoomDetailsHeader), + avatarType = AvatarType.Room( + heroes = persistentListOf( + otherMember.getAvatarData(size = AvatarSize.RoomDetailsHeader) + ), + isTombstoned = isTombstoned, + ), + contentDescription = stringResource(CommonStrings.a11y_room_avatar), + modifier = Modifier + .clip(CircleShape) + .clickable( + enabled = otherMember.avatarUrl != null, + onClickLabel = stringResource(CommonStrings.action_view), + ) { + openAvatarPreview(otherMember.getBestName(), otherMember.avatarUrl!!) + } + .testTag(TestTags.roomDetailAvatar) ) TitleAndSubtitle( title = roomName, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt index fb213ef0cc..23c6292294 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/RoomMemberListStateProvider.kt @@ -128,6 +128,7 @@ fun aRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -138,6 +139,7 @@ fun aRoomMember( isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomMemberList() = persistentListOf( diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt index c7930b5895..08dbf2019d 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsPresenter.kt @@ -160,7 +160,7 @@ class RoomNotificationSettingsPresenter( suspend { val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() pendingModeState.value = null - notificationSettingsService.getRoomNotificationSettings(room.roomId, isEncrypted, room.isOneToOne).getOrThrow() + notificationSettingsService.getRoomNotificationSettings(room.roomId, isEncrypted, room.isDm()).getOrThrow() }.runCatchingUpdatingState(roomNotificationSettings) } @@ -170,7 +170,7 @@ class RoomNotificationSettingsPresenter( val isEncrypted = room.info().isEncrypted ?: room.getUpdatedIsEncrypted().getOrThrow() defaultRoomNotificationMode.value = notificationSettingsService.getDefaultRoomNotificationMode( isEncrypted, - room.isOneToOne + room.isDm() ).getOrThrow() } diff --git a/features/roomdetails/impl/src/main/res/values-be/translations.xml b/features/roomdetails/impl/src/main/res/values-be/translations.xml index 9b89f2cef0..5bd33fef17 100644 --- a/features/roomdetails/impl/src/main/res/values-be/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-be/translations.xml @@ -43,6 +43,7 @@ "Не атрымалася адключыць гук у гэтым пакоі, паўтарыце спробу." "Не ўдалося ўключыць гук у гэтым пакоі. Паўтарыце спробу." "Запрасіць карыстальнікаў" + "Запрасіць" "Пакінуць размову" "Пакінуць пакой" "Уласныя" diff --git a/features/roomdetails/impl/src/main/res/values-bg/translations.xml b/features/roomdetails/impl/src/main/res/values-bg/translations.xml index 55bce6cd12..2c797cb74e 100644 --- a/features/roomdetails/impl/src/main/res/values-bg/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-bg/translations.xml @@ -33,6 +33,7 @@ "Неуспешно заглушаване на тази стая, моля, опитайте отново." "Неуспешно раззаглушаване на тази стая, моля, опитайте отново." "Поканване на хора" + "Поканване" "Напускане на разговора" "Напускане на стаята" "Медия и файлове" diff --git a/features/roomdetails/impl/src/main/res/values-cs/translations.xml b/features/roomdetails/impl/src/main/res/values-cs/translations.xml index eaf787e4e3..d47a1c709b 100644 --- a/features/roomdetails/impl/src/main/res/values-cs/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cs/translations.xml @@ -56,6 +56,7 @@ "Nezavírejte aplikaci, dokud neskončíte." "Příprava pozvánek…" "Pozvat přátele" + "Pozvat" "Opustit konverzaci" "Opustit místnost" "Média a soubory" diff --git a/features/roomdetails/impl/src/main/res/values-cy/translations.xml b/features/roomdetails/impl/src/main/res/values-cy/translations.xml index be8ab00639..b8ec88e51a 100644 --- a/features/roomdetails/impl/src/main/res/values-cy/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-cy/translations.xml @@ -53,6 +53,7 @@ "Peidiwch â chau\'r ap nes ei fod wedi gorffen." "Wrthi\'n paratoi gwahoddiadau…" "Gwahodd pobl" + "Gwahodd" "Gadael y sgwrs" "Gadael yr ystafell" "Cyfryngau a ffeiliau" diff --git a/features/roomdetails/impl/src/main/res/values-da/translations.xml b/features/roomdetails/impl/src/main/res/values-da/translations.xml index 2217e0b9c6..9f3b3436f0 100644 --- a/features/roomdetails/impl/src/main/res/values-da/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-da/translations.xml @@ -56,6 +56,7 @@ "Luk ikke appen, før den er færdig." "Forbereder invitationer…" "Invitér andre" + "Invitér" "Forlad samtalen" "Forlad rum" "Medier og filer" diff --git a/features/roomdetails/impl/src/main/res/values-de/translations.xml b/features/roomdetails/impl/src/main/res/values-de/translations.xml index d810ca0919..c1487d7d98 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -56,6 +56,7 @@ "Schließ die App erst, wenn du fertig bist." "Einladungen werden vorbereitet…" "Nutzer einladen" + "Einladen" "Unterhaltung verlassen" "Verlassen" "Medien und Dateien" diff --git a/features/roomdetails/impl/src/main/res/values-el/translations.xml b/features/roomdetails/impl/src/main/res/values-el/translations.xml index c1b108a524..c1be20d7f5 100644 --- a/features/roomdetails/impl/src/main/res/values-el/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-el/translations.xml @@ -56,6 +56,7 @@ "Μην κλείσετε την εφαρμογή μέχρι να τελειώσει." "Προετοιμασία προσκλήσεων…" "Πρόσκληση ατόμων" + "Πρόσκληση" "Αποχώρηση από τη συζήτηση" "Αποχώρηση από την αίθουσα" "Πολυμέσα και αρχεία" diff --git a/features/roomdetails/impl/src/main/res/values-es/translations.xml b/features/roomdetails/impl/src/main/res/values-es/translations.xml index 716e3ed32a..6b92e48884 100644 --- a/features/roomdetails/impl/src/main/res/values-es/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-es/translations.xml @@ -47,6 +47,7 @@ "No se ha podido silenciar esta sala, inténtalo de nuevo." "Error al dejar de silenciar esta sala, por favor inténtalo de nuevo." "Invitar personas" + "Invitar" "Salir de la conversación" "Salir de la sala" "Medios y archivos" diff --git a/features/roomdetails/impl/src/main/res/values-et/translations.xml b/features/roomdetails/impl/src/main/res/values-et/translations.xml index d5d3af8563..f0c8c58b1f 100644 --- a/features/roomdetails/impl/src/main/res/values-et/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-et/translations.xml @@ -56,6 +56,7 @@ "Ära sulge rakendust enne, kui tegevus on lõppenud." "Valmistan kutseid ette…" "Kutsu osalejaid" + "Kutsu" "Lahku vestlusest" "Lahku jututoast" "Meedia ja failid" diff --git a/features/roomdetails/impl/src/main/res/values-eu/translations.xml b/features/roomdetails/impl/src/main/res/values-eu/translations.xml index 7fb07cf2a4..f299131852 100644 --- a/features/roomdetails/impl/src/main/res/values-eu/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-eu/translations.xml @@ -44,6 +44,7 @@ "Ezin izan da gela mututu; saiatu berriro." "Ezin izan da gela mututzeari utzi; saiatu berriro." "Gonbidatu jendea" + "Gonbidatu" "Utzi elkarrizketa" "Atera gelatik" "Multimedia eta fitxategiak" diff --git a/features/roomdetails/impl/src/main/res/values-fa/translations.xml b/features/roomdetails/impl/src/main/res/values-fa/translations.xml index 364c94c6f2..bb7cb490b8 100644 --- a/features/roomdetails/impl/src/main/res/values-fa/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fa/translations.xml @@ -4,15 +4,15 @@ "هنگام به‌روز کردن تنظیمات آگاهی خطایی رخ داد." "کارساز خانگیتان از این گزینه در اتاق‌های رمز شده پشتیبانی نمی‌کند. ممکن است در برخی اتاق‌ها آگاه نشوید." "نظرسنجی‌ها" - "فقط مدیران" + "ادمین" "تحریم افراد" - "برداشتن پیام‌ها" - "هرکسی" - "دعوت افراد و پذیرش درخواست‌های پیوستن" - "نظارت اعضا" + "حذف پیام‌ها" + "عضو" + "دعوت کاربران" + "مدیریت اعضا" "پیام‌ها و محتوا" - "مدیرن و ناظران" - "برداشتن افراد و رد درخواست‌های پیوستن" + "ناظم" + "حذف افراد" "تغییر چهرک اتاق" "ویرایش جزییات" "تغییر نام اتاق" @@ -51,6 +51,7 @@ "کاره را تا زمان پایانش نبندید." "آماده سازی دعوت‌ها…" "دعوت افراد" + "دعوت" "ترک گفت‌وگو" "ترک اتاق" "رسانه‌ها و پرونده‌ها" @@ -60,7 +61,7 @@ "پیام‌های سنجاق شده" "نمایه" "درخواست‌های پیوستن" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" "امنیت و محرمانگی" "امنیت" "هم‌رسانی اتاق" @@ -79,8 +80,8 @@ "تحریم نکردن از اتاق" "محروم" "اعضا" - "فقط مدیران" - "مدیرن و ناظران" + "ادمین" + "ناظم" "مالک" "اعضای اتاق" "رفع تحریم %1$s" @@ -111,7 +112,7 @@ "بازنشانی اجازه‌ها؟" "نقش‌ها" "جزییات اتاق" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" "افزودن نشانی اتاق" "درخواست دعوت" "بله. به کار انداختن رمزنگاری" diff --git a/features/roomdetails/impl/src/main/res/values-fi/translations.xml b/features/roomdetails/impl/src/main/res/values-fi/translations.xml index 110790fac1..0d07ff4eae 100644 --- a/features/roomdetails/impl/src/main/res/values-fi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fi/translations.xml @@ -56,6 +56,7 @@ "Älä sulje sovellusta ennen kuin se on valmis." "Valmistellaan kutsuja…" "Kutsu henkilöitä" + "Kutsu" "Poistu keskustelusta" "Poistu huoneesta" "Media ja tiedostot" diff --git a/features/roomdetails/impl/src/main/res/values-fr/translations.xml b/features/roomdetails/impl/src/main/res/values-fr/translations.xml index 0fad68c934..3d4283145c 100644 --- a/features/roomdetails/impl/src/main/res/values-fr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-fr/translations.xml @@ -56,6 +56,7 @@ "Ne fermez pas l’application avant que l’opération soit terminée." "Préparation des invitations…" "Inviter des amis" + "Inviter" "Quitter la discussion" "Quitter le salon" "Médias et fichiers" diff --git a/features/roomdetails/impl/src/main/res/values-hr/translations.xml b/features/roomdetails/impl/src/main/res/values-hr/translations.xml index 1bc264ca10..73b6866249 100644 --- a/features/roomdetails/impl/src/main/res/values-hr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hr/translations.xml @@ -56,6 +56,7 @@ "Ne zatvarajte aplikaciju dok se ne završi." "Priprema pozivnica…" "Pozovi osobe" + "Pozovi" "Napusti razgovor" "Napusti sobu" "Mediji i datoteke" diff --git a/features/roomdetails/impl/src/main/res/values-hu/translations.xml b/features/roomdetails/impl/src/main/res/values-hu/translations.xml index 1dc523f319..937c91b68d 100644 --- a/features/roomdetails/impl/src/main/res/values-hu/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hu/translations.xml @@ -56,6 +56,7 @@ "Ne zárja be az alkalmazást, amíg nem végzett." "Meghívók előkészítése…" "Ismerősök meghívása" + "Meghívás" "Beszélgetés elhagyása" "Szoba elhagyása" "Média és fájlok" diff --git a/features/roomdetails/impl/src/main/res/values-in/translations.xml b/features/roomdetails/impl/src/main/res/values-in/translations.xml index 41bf3d2826..2cce124321 100644 --- a/features/roomdetails/impl/src/main/res/values-in/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-in/translations.xml @@ -53,6 +53,7 @@ "Jangan tutup aplikasi tunggu hingga selesai." "Mempersiapkan undangan…" "Undang orang-orang" + "Undang" "Tinggalkan percakapan" "Tinggalkan ruangan" "Media dan berkas" diff --git a/features/roomdetails/impl/src/main/res/values-it/translations.xml b/features/roomdetails/impl/src/main/res/values-it/translations.xml index 22ec99f2b5..044721c345 100644 --- a/features/roomdetails/impl/src/main/res/values-it/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-it/translations.xml @@ -56,6 +56,7 @@ "Non chiudere l\'app fino al completamento." "Preparazione degli inviti…" "Invita persone" + "Invita" "Abbandona la conversazione" "Esci dalla stanza" "File e contenuti multimediali" diff --git a/features/roomdetails/impl/src/main/res/values-ja/translations.xml b/features/roomdetails/impl/src/main/res/values-ja/translations.xml index 70b3255437..b6c7608793 100644 --- a/features/roomdetails/impl/src/main/res/values-ja/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ja/translations.xml @@ -56,6 +56,7 @@ "終了するまでアプリを閉じないでください。" "招待を準備中…" "ユーザーを招待" + "招待" "会話を退出" "ルームを退出" "ファイルとメディア" diff --git a/features/roomdetails/impl/src/main/res/values-ka/translations.xml b/features/roomdetails/impl/src/main/res/values-ka/translations.xml index 3ffc962603..317f62313d 100644 --- a/features/roomdetails/impl/src/main/res/values-ka/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ka/translations.xml @@ -39,6 +39,7 @@ "ამ ოთახის დადუმება ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა." "ამ ოთახის დადუმების მოხსნა ვერ მოხერხდა. გთხოვთ, სცადოთ ხელახლა." "ხალხის მოწვევა" + "მოწვევა" "საუბრის დატოვება" "ოთახის დატოვება" "მორგებული" diff --git a/features/roomdetails/impl/src/main/res/values-ko/translations.xml b/features/roomdetails/impl/src/main/res/values-ko/translations.xml index 2c6462c4a7..8c0db6eefd 100644 --- a/features/roomdetails/impl/src/main/res/values-ko/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ko/translations.xml @@ -56,6 +56,7 @@ "작업이 완료될 때까지 앱을 닫지 마세요." "초대 준비중…" "사람 초대하기" + "초대" "대화에서 나가기" "방 떠나기" "미디어 및 파일" diff --git a/features/roomdetails/impl/src/main/res/values-lt/translations.xml b/features/roomdetails/impl/src/main/res/values-lt/translations.xml index 84f74042da..9bdaeb86e5 100644 --- a/features/roomdetails/impl/src/main/res/values-lt/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-lt/translations.xml @@ -8,6 +8,7 @@ "Žinutės yra užrakintos. Tik Jūs ir gavėjai turite unikalius raktus joms atrakinti." "Įjungtas žinučių šifravimas" "Pakviesti žmonių" + "Kviesti" "Palikti pokalbį" "Išeiti iš kambario" "Pasirinktinis" diff --git a/features/roomdetails/impl/src/main/res/values-nb/translations.xml b/features/roomdetails/impl/src/main/res/values-nb/translations.xml index e522f5cd79..52ea87bc3d 100644 --- a/features/roomdetails/impl/src/main/res/values-nb/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nb/translations.xml @@ -56,6 +56,7 @@ "Ikke lukk appen før den er ferdig." "Forbereder invitasjoner…" "Inviter folk" + "Inviter" "Forlat samtalen" "Forlat rommet" "Medier og filer" diff --git a/features/roomdetails/impl/src/main/res/values-nl/translations.xml b/features/roomdetails/impl/src/main/res/values-nl/translations.xml index 9234921c35..e9f03d3a57 100644 --- a/features/roomdetails/impl/src/main/res/values-nl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-nl/translations.xml @@ -43,6 +43,7 @@ "Het dempen van deze kamer is mislukt. Probeer het opnieuw." "Het dempen opheffen voor deze kamer is mislukt. Probeer het opnieuw." "Mensen uitnodigen" + "Uitnodigen" "Gesprek verlaten" "Kamer verlaten" "Media en bestanden" diff --git a/features/roomdetails/impl/src/main/res/values-pl/translations.xml b/features/roomdetails/impl/src/main/res/values-pl/translations.xml index e22636290b..7af5d8e557 100644 --- a/features/roomdetails/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pl/translations.xml @@ -1,19 +1,24 @@ - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" + "Nowi członkowie nie widzą historii" + "Nowi członkowie widzą historię" + "Każdy może przeglądać historię" + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Edytuj adres" "Wystąpił błąd podczas aktualizacji ustawienia powiadomień." "Twój serwer domowy nie wspiera tej opcji w pokojach szyfrowanych, możesz nie otrzymać powiadomień z niektórych pokoi." "Ankiety" - "Tylko administratorzy" + "Administrator" "Banowanie osób" "Usuń wiadomości" - "Zapraszanie osób i akceptowanie próśb o dołączenie" + "Członek" + "Zaproś osoby" + "Zarządzaj członkami" "Wiadomości i zawartość" - "Administratorzy i moderatorzy" - "Usuwanie osób i odrzucanie próśb o dołączenie" + "Moderator" + "Usuń osoby" "Zmień awatar pokoju" - "Edytuj pokój" + "Edytuj szczegóły" "Zmień nazwę pokoju" "Zmień temat pokoju" "Wysyłanie wiadomości" @@ -26,7 +31,7 @@ "Nie będzie można cofnąć tej zmiany, jeśli się zdegradujesz. Jeśli jesteś ostatnim uprzywilejowanym użytkownikiem w pokoju, nie będziesz w stanie odzyskać uprawnień." "Zdegradować siebie?" "%1$s (Oczekujące)" - "(Oczekujący)" + "(Oczekujące)" "Administratorzy automatycznie mają uprawnienia moderatora" "Właściciele automatycznie mają uprawnienia administratora." "Edytuj moderatorów" @@ -40,7 +45,7 @@ "Szyfrowany" "Nieszyfrowany" "Pokój publiczny" - "Edytuj pokój" + "Edytuj szczegóły" "Wystąpił nieznany błąd i nie można było zmienić informacji." "Nie można zaktualizować pokoju" "Wiadomości są zabezpieczone kłódkami. Tylko Ty i odbiorcy macie unikalne klucze do ich odblokowania." @@ -51,6 +56,7 @@ "Nie zamykaj aplikacji przed zakończeniem." "Przygotowywanie zaproszeń…" "Zaproś znajomych" + "Zaproś" "Opuść rozmowę" "Opuść pokój" "Media i pliki" @@ -61,13 +67,21 @@ "Profil" "Prośby o dołączenie" "Role i uprawnienia" + "Nazwa" "Bezpieczeństwo i prywatność" "Bezpieczeństwo" "Udostępnij pokój" "Informacje pokoju" "Temat" "Aktualizuję pokój…" - "W tym pokoju nie ma zbanowanych użytkowników." + "Nie ma zbanowanych użytkowników." + + "%1$d zbanowany" + "%1$d zbanowanych" + "%1$d zbanowanych" + + "Sprawdź pisownię lub wyszukaj ponownie" + "Brak wyników dla “%1$s”" "%1$d osoba" "%1$d osoby" @@ -80,8 +94,14 @@ "Odbanuj z pokoju" "Zbanowanych" "Członków" - "Tylko administratorzy" - "Administratorzy i moderatorzy" + + "%1$d zaproszony" + "%1$d zaproszonych" + "%1$d zaproszonych" + + "Oczekuje" + "Administrator" + "Moderator" "Właściciel" "Członkowie pokoju" "Odbanowanie %1$s" @@ -108,15 +128,18 @@ "Wiadomości i zawartość" "Moderatorzy" "Właściciele" - "Resetuj uprawnienia" + "Uprawnienia" + "Zresetuj uprawnienia" "Po zresetowaniu uprawnień utracisz bieżące ustawienia." "Zresetować uprawnienia?" "Role" "Szczegóły pokoju" "Role i uprawnienia" - "Dodaj adres pokoju" - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić żądanie." + "Dodaj adres" + "Każdy w autoryzowanych przestrzeniach może dołączyć, ale wszyscy inni muszą poprosić o dostęp." + "Każdy musi poprosić o dostęp." "Poproś o dołączenie" + "Każdy w %1$s może dołączyć, ale wszyscy pozostali muszą poprosić o dostęp." "Tak, włącz szyfrowanie" "Po włączeniu szyfrowanie pokoju nie może zostać wyłączone, a historia wiadomości będzie widoczna tylko dla członków od momentu, w którym dołączyli lub zostali zaproszeni. Nikt poza członkami pokoju nie będzie mógł czytać wiadomości. Może to wpłynąć na prawidłowe działanie botów lub mostków. @@ -125,23 +148,31 @@ Odradzamy włączanie szyfrowania dla pokoi, które każdy może znaleźć i do "Po włączeniu szyfrowania nie można wyłączyć." "Szyfrowanie" "Włącz szyfrowanie end-to-end" - "Każdy może znaleźć i dołączyć" + "Każdy może dołączyć." "Każdy" - "Tylko osoby z zaproszeniem mogą dołączyć" - "Tylko zaproszenie" - "Dostęp do pokoju" + "Wybierz, którzy członkowie przestrzeni mogą dołączyć do tego pokoju bez zaproszenia. %1$s" + "Zarządzaj przestrzeniami" + "Tylko zaproszone osoby mogą dołączyć" + "Tylko na zaproszenie" + "Dostęp" + "Każdy w autoryzowanych przestrzeniach może dołączyć." + "Każdy w %1$s może dołączyć." + "Członkowie przestrzeni" "Przestrzenie nie są obecnie wspierane" - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Adres" "Zezwól na znalezienie tego pokoju wyszukując %1$s w katalogu pokoi publicznych" + "Zezwól, by inni mogli Cię znaleźć, przeszukując katalog publiczny." "Widoczny w katalogu pokoi publicznych" - "Ktokolwiek" + "Każdy (historia jest publiczna)" + "Zmiany nie zmienią przeszłych wiadomości, tylko nowe. %1$s" "Kto może czytać historię" - "Od momentu kiedy członkowie zostali zaproszeni" - "Członkowie od momentu włączenia tej opcji" + "Członkowie od kiedy zostali zaproszeni" + "Członkowie (cała historia)" "Adresy pokoju umożliwiają łatwe znalezienie i dołączenie do pokojów. Również możesz się zdecydować na upublicznienie Twojego serwera w katalogu pokoi publicznych." "Publikowanie pokoju" - "Widoczność pokoju" + "Adresy pokoi pomagają w znalezieniu i dołączeniu do pokoi i przestrzeni. Umożliwiają również łatwe udostępnianie ich innym." + "Widoczność" "Bezpieczeństwo i prywatność" diff --git a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml index ddbbe0f601..da98e7bd5a 100644 --- a/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt-rBR/translations.xml @@ -53,6 +53,7 @@ "Não feche o aplicativo até terminar." "Preparando convites…" "Convidar pessoas" + "Convidar" "Sair da conversa" "Sair da sala" "Mídia e arquivos" diff --git a/features/roomdetails/impl/src/main/res/values-pt/translations.xml b/features/roomdetails/impl/src/main/res/values-pt/translations.xml index 592cba34f6..c5a9be9a4c 100644 --- a/features/roomdetails/impl/src/main/res/values-pt/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-pt/translations.xml @@ -53,6 +53,7 @@ "Não feches a aplicação até concluir." "A preparar convites…" "Convidar pessoas" + "Convidar" "Sair da conversa" "Sair da sala" "Multimédia e ficheiros" diff --git a/features/roomdetails/impl/src/main/res/values-ro/translations.xml b/features/roomdetails/impl/src/main/res/values-ro/translations.xml index 2eac873575..0374c64314 100644 --- a/features/roomdetails/impl/src/main/res/values-ro/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ro/translations.xml @@ -53,6 +53,7 @@ "Nu închideți aplicația până nu se termină." "Se pregătesc invitațiile…" "Invitați prieteni" + "Invitați" "Părăsiți conversația" "Părăsiți camera" "Media și fișiere" diff --git a/features/roomdetails/impl/src/main/res/values-ru/translations.xml b/features/roomdetails/impl/src/main/res/values-ru/translations.xml index 7ad44fff9d..bd683009ad 100644 --- a/features/roomdetails/impl/src/main/res/values-ru/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ru/translations.xml @@ -56,6 +56,7 @@ "Не закрывайте приложение, пока не закончите." "Подготовка приглашений…" "Пригласить в комнату" + "Пригласить" "Покинуть беседу" "Покинуть комнату" "Медиа и файлы" diff --git a/features/roomdetails/impl/src/main/res/values-sk/translations.xml b/features/roomdetails/impl/src/main/res/values-sk/translations.xml index 225dcedac3..6a27e375ee 100644 --- a/features/roomdetails/impl/src/main/res/values-sk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sk/translations.xml @@ -53,6 +53,7 @@ "Nezatvárajte aplikáciu, kým sa neukončí pozývanie." "Príprava pozvánok…" "Pozvať ľudí" + "Pozvať" "Opustiť konverzáciu" "Opustiť miestnosť" "Médiá a súbory" diff --git a/features/roomdetails/impl/src/main/res/values-sv/translations.xml b/features/roomdetails/impl/src/main/res/values-sv/translations.xml index 795dc97106..02574e77e9 100644 --- a/features/roomdetails/impl/src/main/res/values-sv/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-sv/translations.xml @@ -53,6 +53,7 @@ "Stäng inte appen förrän det är klart." "Förbereder inbjudningar …" "Bjud in personer" + "Bjud in" "Lämna konversation" "Lämna rum" "Media och filer" diff --git a/features/roomdetails/impl/src/main/res/values-tr/translations.xml b/features/roomdetails/impl/src/main/res/values-tr/translations.xml index 16137ce753..8d11b8035a 100644 --- a/features/roomdetails/impl/src/main/res/values-tr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-tr/translations.xml @@ -46,6 +46,7 @@ "Bu odayı sessize alma başarısız oldu, lütfen tekrar deneyin." "Bu odanın sesi açılamadı, lütfen tekrar deneyin." "Kişileri davet et" + "Davet et" "Sohbeti bırak" "Odadan ayrıl" "Medya ve dosyalar" diff --git a/features/roomdetails/impl/src/main/res/values-uk/translations.xml b/features/roomdetails/impl/src/main/res/values-uk/translations.xml index 46adfa54d5..1565e0ec48 100644 --- a/features/roomdetails/impl/src/main/res/values-uk/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uk/translations.xml @@ -1,5 +1,8 @@ + "Нові учасники не бачать історії" + "Нові учасники бачать історію" + "Будь-хто може переглянути історію" "Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі." "Змінити адресу" "Під час оновлення налаштувань сповіщень сталася помилка." @@ -53,6 +56,7 @@ "Не закривайте застосунок доки не завершите." "Приготування запрошень…" "Запросити людей" + "Запросити" "Залишити розмову" "Вийти з кімнати" "Медіа та файли" @@ -71,6 +75,11 @@ "Тема" "Оновлення кімнати…" "Немає заблокованих користувачів." + + "%1$d Заблокований" + "%1$d Заблоковано" + "%1$d Заблоковано" + "Перевірте правопис або спробуйте новий пошук" "Немає результатів за запитом «%1$s»" @@ -127,8 +136,10 @@ "Деталі кімнати" "Ролі та дозволи" "Додати адресу" + "Будь-хто в авторизованих просторах може приєднатися, але всі інші повинні подати запит на доступ." "Усі повинні запитувати доступ." "Запит на приєднання" + "Будь-хто з %1$s може приєднатися, але всі інші повинні подати запит на доступ." "Так, увімкнути шифрування" "Після ввімкнення шифрування кімнати, його неможливо вимкнути, історію повідомлень бачитимуть лише учасники кімнати, яких було запрошено або які приєдналися до кімнати. Ніхто, крім учасників кімнати, не зможе прочитати повідомлення. Це може перешкоджати коректній роботі ботів і мостів. @@ -144,11 +155,14 @@ "Приєднатися можуть лише запрошені люди." "Лише запрошені" "Доступ" + "Долучитися може будь-хто, хто має доступ до авторизованих просторів." "Долучитися може будь-хто з %1$s." + "Учасники простору" "Простори наразі не підтримуються" "Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі." "Адреса" "Дозвольте, щоб цю кімнату можна було знайти за допомогою пошуку в каталозі загальнодоступних кімнат %1$s " + "Дозвольте знаходити вас за допомогою пошуку в публічному каталозі." "Видима в загальному каталозі" "Будь-хто (загальнодоступна історія)" "Зміни не вплинуть на попередні повідомлення, лише на нові. %1$s" @@ -158,6 +172,7 @@ "Адреси кімнат — це спосіб знайти кімнату та отримати до неї доступ. Це також гарантує, що ви можете легко поділитися своєю кімнатою з іншими. Ви можете опублікувати свою кімнату в каталозі загальнодоступних кімнат вашого домашнього сервера." "Публікація в кімнаті" + "Адреси — це спосіб знаходити кімнати та простори та отримувати до них доступ. Це також гарантує, що ви зможете легко ділитися ними з іншими." "Видимість" "Безпека й приватність" diff --git a/features/roomdetails/impl/src/main/res/values-ur/translations.xml b/features/roomdetails/impl/src/main/res/values-ur/translations.xml index 3715bb91ff..d5ab09dd18 100644 --- a/features/roomdetails/impl/src/main/res/values-ur/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-ur/translations.xml @@ -43,6 +43,7 @@ "اس کمرے کو خاموش کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔" "اس کمرے کو غیر خاموش کرنے میں ناکام، برائے مہربانی دوبارہ کوشش کریں۔" "لوگوں کو مدعو کریں" + "مدعو کریں" "گفتگو چھوڑیں" "کمرہ چھوڑ دیں" "حسب ضرورت" diff --git a/features/roomdetails/impl/src/main/res/values-uz/translations.xml b/features/roomdetails/impl/src/main/res/values-uz/translations.xml index 1b4718ee44..fa9408b3ba 100644 --- a/features/roomdetails/impl/src/main/res/values-uz/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uz/translations.xml @@ -56,6 +56,7 @@ "Tugallanmaguncha ilovani yopmang." "Taklifnomalar tayyorlanmoqda…" "Odamlarni taklif qiling" + "Taklif qilish" "Suhbatni tark etish" "Xonani tark etish" "Media va fayllar" diff --git a/features/roomdetails/impl/src/main/res/values-vi/translations.xml b/features/roomdetails/impl/src/main/res/values-vi/translations.xml index ac37e6fcfa..5e25014c88 100644 --- a/features/roomdetails/impl/src/main/res/values-vi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-vi/translations.xml @@ -46,6 +46,7 @@ "Không thể tắt tiếng phòng này, vui lòng thử lại." "Không thể bật tiếng cho phòng này. Vui lòng thử lại." "Mời ai đó" + "Mời" "Rời khỏi cuộc trò chuyện" "Rời phòng" "Tùy chỉnh" diff --git a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml index 1cbabe0e54..04ccc56adb 100644 --- a/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh-rTW/translations.xml @@ -56,6 +56,7 @@ "完成前請勿關閉應用程式。" "正在準備邀請……" "邀請夥伴" + "邀請" "離開對話" "離開聊天室" "媒體與檔案" diff --git a/features/roomdetails/impl/src/main/res/values-zh/translations.xml b/features/roomdetails/impl/src/main/res/values-zh/translations.xml index 267cdf5c04..1fef5583a3 100644 --- a/features/roomdetails/impl/src/main/res/values-zh/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-zh/translations.xml @@ -56,6 +56,7 @@ "完成之前请勿关闭 app。" "正在准备邀请…" "邀请人员" + "邀请" "离开聊天" "离开房间" "媒体与文件" diff --git a/features/roomdetails/impl/src/main/res/values/localazy.xml b/features/roomdetails/impl/src/main/res/values/localazy.xml index 6275b2837e..d7092af70e 100644 --- a/features/roomdetails/impl/src/main/res/values/localazy.xml +++ b/features/roomdetails/impl/src/main/res/values/localazy.xml @@ -56,6 +56,7 @@ "Don\'t close the app until finished." "Preparing invitations…" "Invite people" + "Invite" "Leave conversation" "Leave room" "Media and files" diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt index d355010307..9c116f5a9d 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsPresenterTest.kt @@ -21,9 +21,6 @@ import io.element.android.libraries.androidutils.clipboard.ClipboardHelper import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags -import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.RoomMembersState @@ -80,11 +77,6 @@ class RoomDetailsPresenterTest { dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(), analyticsService: AnalyticsService = FakeAnalyticsService(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService( - mapOf( - FeatureFlags.Knock.key to false, - ) - ), encryptionService: FakeEncryptionService = FakeEncryptionService(), clipboardHelper: ClipboardHelper = FakeClipboardHelper(), appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore() @@ -106,7 +98,6 @@ class RoomDetailsPresenterTest { return RoomDetailsPresenter( client = matrixClient, room = room, - featureFlagService = featureFlagService, notificationSettingsService = matrixClient.notificationSettingsService, roomMembersDetailsPresenterFactory = roomMemberDetailsPresenterFactory, leaveRoomPresenter = { leaveRoomState }, @@ -199,19 +190,14 @@ class RoomDetailsPresenterTest { givenRoomInfo( aRoomInfo( isEncrypted = true, - isDirect = true, + isDm = true, ) ) } val presenter = createRoomDetailsPresenter(room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { val initialState = awaitItem() - assertThat(initialState.roomType).isEqualTo( - RoomDetailsType.Dm( - me = myRoomMember, - otherMember = otherRoomMember, - ) - ) + assertThat(initialState.roomType).isEqualTo(RoomDetailsType.Dm(otherMember = otherRoomMember)) cancelAndIgnoreRemainingEvents() } } @@ -289,7 +275,7 @@ class RoomDetailsPresenterTest { givenRoomInfo( aRoomInfo( isEncrypted = true, - isDirect = true, + isDm = true, ) ) } @@ -312,7 +298,6 @@ class RoomDetailsPresenterTest { val myRoomMember = aRoomMember(A_SESSION_ID) val otherRoomMember = aRoomMember(A_USER_ID_2) val room = aJoinedRoom( - isDirect = true, topic = null, roomPermissions = roomPermissions(), userDisplayNameResult = { Result.success(A_USER_NAME) }, @@ -330,7 +315,7 @@ class RoomDetailsPresenterTest { givenRoomInfo( aRoomInfo( - isDirect = true, + isDm = true, activeMembersCount = 2, topic = null, ) @@ -570,17 +555,11 @@ class RoomDetailsPresenterTest { roomPermissions = roomPermissions(), joinRule = JoinRule.Knock, ) - val featureFlagService = FakeFeatureFlagService( - mapOf(FeatureFlags.Knock.key to false) - ) val presenter = createRoomDetailsPresenter( room = room, - featureFlagService = featureFlagService, ) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { skipItems(1) - assertThat(awaitItem().canShowKnockRequests).isFalse() - featureFlagService.setFeatureEnabled(FeatureFlags.Knock, true) assertThat(awaitItem().canShowKnockRequests).isTrue() room.givenRoomInfo(aRoomInfo(joinRule = JoinRule.Invite)) assertThat(awaitItem().canShowKnockRequests).isFalse() @@ -593,8 +572,7 @@ class RoomDetailsPresenterTest { val room = aJoinedRoom( roomPermissions = roomPermissions(), ) - val featureFlagService = FakeFeatureFlagService() - val presenter = createRoomDetailsPresenter(room = room, featureFlagService = featureFlagService) + val presenter = createRoomDetailsPresenter(room = room) presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) { skipItems(1) with(awaitItem()) { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt index 50139e0149..5fe0130c73 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsViewTest.kt @@ -126,10 +126,7 @@ class RoomDetailsViewTest { state = aRoomDetailsState( eventSink = EventsRecorder(expectEvents = false), canInvite = true, - roomType = RoomDetailsType.Dm( - aRoomMember(UserId("@me:local.org")), - aRoomMember(UserId("@other:local.org")) - ), + roomType = RoomDetailsType.Dm(aRoomMember(UserId("@other:local.org"))), ), onJoinCallClick = callback, ) @@ -232,10 +229,7 @@ class RoomDetailsViewTest { fun `click on avatar test on DM`() = runAndroidComposeUiTest { val eventsRecorder = EventsRecorder(expectEvents = false) val state = aRoomDetailsState( - roomType = RoomDetailsType.Dm( - aRoomMember(), - aDmRoomMember(avatarUrl = "an_avatar_url"), - ), + roomType = RoomDetailsType.Dm(aDmRoomMember(avatarUrl = "an_avatar_url"),), roomName = "Daniel", eventSink = eventsRecorder, ) @@ -244,7 +238,7 @@ class RoomDetailsViewTest { state = state, openAvatarPreview = callback, ) - onNodeWithTag(TestTags.memberDetailAvatar.value).performClick() + onNodeWithTag(TestTags.roomDetailAvatar.value).performClick() callback.assertSuccess() } diff --git a/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml b/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml index c676ff46ed..25be496204 100644 --- a/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml +++ b/features/roomdetailsedit/impl/src/main/res/values-pl/translations.xml @@ -1,6 +1,6 @@ - "Edytuj pokój" + "Edytuj szczegóły" "Wystąpił nieznany błąd i nie można było zmienić informacji." "Nie można zaktualizować pokoju" "Aktualizuję pokój…" diff --git a/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml b/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml index f17660f418..6ddb482189 100644 --- a/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-fa/translations.xml @@ -9,7 +9,7 @@ "در صورت دعوت می‌تواند دوباره به اتاق بپیوندد." "مطمئنید می‌خواهید این عضو را بردارید؟" "دیدن نمایه" - "برداشتن از اتاق" + "حذف کاربر" "برداشتن عضو و تحریم پیوستن در آینده؟" "برداشتن %1$s…" "تحریم نکردن از اتاق" diff --git a/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml b/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml index 20246af787..40ea1f099a 100644 --- a/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-pl/translations.xml @@ -4,12 +4,14 @@ "Zbanuj" "Nie będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." "Czy na pewno chcesz zbanować tego członka?" + "Nie będą mogli ponownie dołączyć do tej przestrzeni, nawet jeśli zostaną zaproszeni, zachowają jednak członkostwo w pokojach lub podprzestrzeniach." "Banowanie %1$s" "Usuń" "Będą mogli ponownie dołączyć do tego pokoju, jeśli zostaną zaproszeni." "Czy na pewno chcesz usunąć tego członka?" + "Będą mogli ponownie dołączyć do tej przestrzeni, jeśli zostaną zaproszeni, zachowując jednocześnie członkostwo w pokojach lub podprzestrzeniach." "Wyświetl profil" - "Usuń z pokoju" + "Usuń użytkownika" "Usunąć członka i zablokować możliwość dołączenia w przyszłości?" "Usuwanie %1$s…" "Odbanuj z pokoju" diff --git a/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml b/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml index cd6dd40e55..0ddc115f7d 100644 --- a/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml +++ b/features/roommembermoderation/impl/src/main/res/values-uk/translations.xml @@ -4,10 +4,12 @@ "Заблокувати" "Він не зможе приєднатися до цієї кімнати знову, якщо його запросять." "Ви точно хочете заблокувати цього користувача?" + "Вони не зможуть знову приєднатися до цього простору, навіть якщо їх запросять, але збережуть своє членство в будь-яких кімнатах або підпросторах." "Блокування %1$s" "Вилучити" "Вони зможуть знову приєднатися до цієї кімнати, якщо їх запросять." "Ви дійсно хочете вилучити цього учасника?" + "Вони зможуть знову приєднатися до цього простору, якщо їх запросять, і збережуть своє членство в будь-яких кімнатах або підпросторах." "Переглянути профіль" "Вилучити користувача" "Вилучити учасника та заборонити приєднання в майбутньому?" diff --git a/features/securebackup/impl/src/main/res/values-el/translations.xml b/features/securebackup/impl/src/main/res/values-el/translations.xml index ca9adbc5ac..0f4584271c 100644 --- a/features/securebackup/impl/src/main/res/values-el/translations.xml +++ b/features/securebackup/impl/src/main/res/values-el/translations.xml @@ -12,6 +12,7 @@ "Εισαγωγή κλειδιού ανάκτησης" "Ο αποθηκευτικός χώρος κλειδιών σου δεν είναι συγχρονισμένος αυτήν τη στιγμή." "Λήψη κλειδιού ανάκτησης" + "Οι συνομιλίες σας αποθηκεύονται αυτόματα με κρυπτογράφηση από άκρο σε άκρο. Για να επαναφέρετε αυτό το αντίγραφο ασφαλείας και να διατηρήσετε την ψηφιακή σας ταυτότητα όταν χάσετε την πρόσβαση σε όλες τις συσκευές σας, θα χρειαστείτε το κλειδί ανάκτησης. " "Άνοιγμα %1$s σε συσκευή υπολογιστή" "Συνδέσου ξανά στο λογαριασμό σου" "Όταν σου ζητηθεί να επαληθεύσεις τη συσκευή σου, επέλεξε %1$s" diff --git a/features/securebackup/impl/src/main/res/values-et/translations.xml b/features/securebackup/impl/src/main/res/values-et/translations.xml index 987fd88190..c3d849f37b 100644 --- a/features/securebackup/impl/src/main/res/values-et/translations.xml +++ b/features/securebackup/impl/src/main/res/values-et/translations.xml @@ -61,9 +61,9 @@ "Seadista andmete taastamine" "Jah, lähtesta nüüd" "See tegevus on tagasipöördumatu." - "Kas sa oled kindel, et soovid oma andmete krüptimist lähtestada?" + "Kas sa oled kindel, et soovid oma võrguidentiteeti lähtestada?" "Tekkis teadmata viga. Palun kontrolli, kas sinu kasutajakonto salasõna on õige ja proovi uuesti." "Sisesta…" - "Palun kinnita, et soovid oma andmete krüptimist lähtestada." + "Palun kinnita, et soovid oma võrguidentiteedi lähtestada." "Jätkamaks sisesta oma kasutajakonto salasõna" diff --git a/features/securebackup/impl/src/main/res/values-fa/translations.xml b/features/securebackup/impl/src/main/res/values-fa/translations.xml index c16e5bd1d8..bd7a43ffba 100644 --- a/features/securebackup/impl/src/main/res/values-fa/translations.xml +++ b/features/securebackup/impl/src/main/res/values-fa/translations.xml @@ -9,7 +9,7 @@ "تغییر کلید بازیابی" "ورود کلید بازیابی" "ذخیره‌ساز کلیدتان از هم‌گام بودن در آمده." - "برپایی بازیابی" + "دریافت کلید بازیابی" "گشودن %1$s در افزارهٔ میزکار" "ورود دوباره به حسابتان" "گزینش %1$s هنگام درخواست تأیید افزاره‌تان" @@ -23,10 +23,10 @@ "لازم است دوباره همهٔ آشنایان و افزاره‌های موجودتان را تأیید کنید" "فقط اگر به افزاره‌ای وارد شده از پیش دسترسی ندارید و کلید بازیابیتان را گم کرده‌اید بازنشانی کنید." "نمی‌توانید تأیید کنید؟ لازم است هویتتان را بازنشانی کنید." - "خاموش کردن" - "اگر از سیستم همه دستگاه ها خارج شده باشید، پیام های رمزگذاری شده خود را از دست خواهید داد." - "مطمئنید که می‌خواهید پشتیبان گیری را خاموش کنید؟" - "حذف فضای ذخیره سازی کلید، هویت رمزنگاری و کلیدهای پیام شما را از کارساز حذف می کند و ویژگی های امنیتی زیر را خاموش می کند:" + "حذف" + "اگر از تمام دستگاه‌هایتان خارج شوید، تاریخچه چت رمزگذاری‌شده خود را از دست خواهید داد و باید هویت دیجیتال خود را مجدداً تنظیم کنید." + "آیا مطمئن هستید که می‌خواهید کلید ذخیره‌سازی را حذف کنید؟" + "حذف محل ذخیره‌سازی کلید، کلیدهای هویت دیجیتال و پیام شما را از سرور حذف کرده و ویژگی‌های امنیتی زیر را غیرفعال می‌کند:" "سابقه پیام رمزگذاری شده در دستگاه های جدید نخواهید داشت" "اگر از %1$s در همه جا خارج شده باشید، دسترسی به پیام های رمزگذاری شده خود را از دست خواهید داد" "مطمئنید که می‌خواهید فضای ذخیره سازی کلید را خاموش کرده و آن را حذف کنید؟" @@ -56,7 +56,7 @@ "تولید کلید بازیابیتان" "با کسی هم‌رسانیش نکنید!" "برپایی بازیابی موفّق بود" - "برپایی بازیابی" + "دریافت کلید بازیابی" "بله. اکنون بازنشانی شود" "این فرایند بازگشت‌ناپذیر است." "ورود…" diff --git a/features/securebackup/impl/src/main/res/values-pl/translations.xml b/features/securebackup/impl/src/main/res/values-pl/translations.xml index fb30d786c0..f2f44e10f3 100644 --- a/features/securebackup/impl/src/main/res/values-pl/translations.xml +++ b/features/securebackup/impl/src/main/res/values-pl/translations.xml @@ -2,33 +2,34 @@ "Wyłącz backup" "Włącz backup" - "Bezpiecznie przechowuj swoją tożsamość kryptograficzną i klucze wiadomości na serwerze. Umożliwi to przeglądanie historii wiadomości na każdym nowym urządzeniu. %1$s" + "Umożliwi Ci to przeglądanie historii czatów na nowych urządzeniach i jest wymagane do tworzenia kopii zapasowych i tożsamości cyfrowej. %1$s." "Magazyn kluczy" - "Magazyn kluczy musi być włączony, aby włączyć przywracanie." + "Magazyn kluczy musi być włączony, aby włączyć archiwizowanie czatów." "Prześlij klucze z tego urządzenia" "Zezwól na magazynowanie kluczy" "Zmień klucz przywracania" - "Odzyskaj swoją tożsamość kryptograficzną i historię wiadomości za pomocą klucza przywracania, jeśli utraciłeś dostęp do wszystkich swoich urządzeń." + "Twoje czaty są automatycznie archiwizowane za pomocą szyfrowania end-to-end. Aby przywrócić tę kopię zapasową i swoją tożsamość cyfrową, wymagany będzie klucz przywracania." "Wprowadź klucz przywracania" "Magazyn kluczy nie jest zsynchronizowany." - "Skonfiguruj przywracanie" + "Uzyskaj klucz przywracania" + "Twoje czaty są automatycznie archiwizowane za pomocą szyfrowania end-to-end. Aby przywrócić tę kopię zapasową i swoją tożsamość cyfrową, wymagany będzie klucz przywracania." "Otwórz %1$s na urządzeniu stacjonarnym" "Zaloguj się ponownie na swoje konto" "Gdy pojawi się prośba o weryfikację urządzenia, wybierz %1$s" - "“Resetuj wszystko”" + "“Zresetuj wszystko”" "Postępuj zgodnie z instrukcjami, aby utworzyć nowy klucz przywracania" "Zapisz nowy klucz przywracania w menedżerze haseł lub notatce szyfrowanej" - "Resetuj szyfrowanie swojego konta za pomocą drugiego urządzenia" + "Zresetuj szyfrowanie swojego konta za pomocą drugiego urządzenia" "Kontynuuj resetowanie" "Szczegóły konta, kontakty, preferencje i lista czatów zostaną zachowane" "Utracisz istniejącą historię wiadomości" "Wymagana będzie ponowna weryfikacja istniejących urządzeń i kontaktów" - "Zresetuj swoją tożsamość tylko wtedy, gdy nie jesteś zalogowany na żadnym urządzeniu i straciłeś swój klucz przywracania." - "Zresetuj swoją tożsamość, jeśli nie możesz jej potwierdzić w inny sposób" - "Wyłącz" - "Jeśli wylogujesz się ze wszystkich urządzeń, stracisz wszystkie wiadomości szyfrowane." - "Czy na pewno chcesz wyłączyć backup?" - "Wyłączenie backupu spowoduje usunięcie kopii klucza szyfrowania i wyłączenie innych funkcji bezpieczeństwa. W takim przypadku będziesz:" + "Zresetuj swoją tożsamość tylko wtedy, gdy nie posiadasz dostępu do żadnego innego zweryfikowanego urządzenia i straciłeś swój klucz przywracania." + "Nie możesz potwierdzić? Zresetuj swoją tożsamość cyfrową." + "Usuń" + "Jeśli usuniesz wszystkie swoje urządzenia, stracisz zaszyfrowaną historię wiadomości i będziesz musiał zresetować swoją tożsamość cyfrową." + "Czy na pewno chcesz usunąć magazyn kluczy?" + "Usunięcie magazynu kluczy usunie Twoją tożsamość cyfrową i klucze wiadomości z serwera, wyłączając następujące funkcje bezpieczeństwa:" "Posiadał historii wiadomości szyfrowanych na nowych urządzeniach" "Utracisz dostęp do wiadomości szyfrowanych, jeśli zostaniesz wszędzie wylogowany z %1$s" "Czy na pewno chcesz wyłączyć backup?" @@ -58,12 +59,12 @@ "Wygeneruj klucz przywracania" "Nie udostępniaj tego nikomu!" "Skonfigurowano przywracanie pomyślnie" - "Skonfiguruj przywracanie" + "Uzyskaj klucz przywracania" "Tak, zresetuj teraz" "Tego procesu nie można odwrócić." - "Czy na pewno chcesz zresetować szyfrowanie?" + "Czy na pewno chcesz zresetować swoją tożsamość cyfrową?" "Wystąpił nieznany błąd. Sprawdź, czy hasło jest poprawne i spróbuj ponownie." "Wprowadź…" - "Potwierdź, że chcesz zresetować szyfrowanie." + "Potwierdź, że chcesz zresetować swoją tożsamość cyfrową." "Wprowadź hasło, aby kontynuować" diff --git a/features/securebackup/impl/src/main/res/values-sk/translations.xml b/features/securebackup/impl/src/main/res/values-sk/translations.xml index b02d5ecfbb..3e92a39df0 100644 --- a/features/securebackup/impl/src/main/res/values-sk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-sk/translations.xml @@ -26,7 +26,7 @@ "Obnovte svoju totožnosť iba vtedy, ak nemáte prístup k inému prihlásenému zariadeniu a stratili ste kľúč na obnovenie." "Znovu nastavte svoju totožnosť v prípade, že ju nemôžete potvrdiť iným spôsobom" "Vypnúť" - "Stratíte prístup k svojim zašifrovaným správam, ak sa odhlásite zo všetkých zariadení" + "Ak odstránite všetky svoje zariadenia, stratíte svoju zašifrovanú históriu správ a budete si musieť obnoviť svoju digitálnu identitu." "Ste si istí, že chcete vypnúť zálohovanie?" "Vypnutím zálohovania sa odstráni aktuálna záloha šifrovacích kľúčov a vypnú sa ďalšie bezpečnostné funkcie. V tomto prípade:" "Na nových zariadeniach nebudete mať zašifrovanú históriu správ" diff --git a/features/securebackup/impl/src/main/res/values-uk/translations.xml b/features/securebackup/impl/src/main/res/values-uk/translations.xml index 218e6d64fd..82a96fcab9 100644 --- a/features/securebackup/impl/src/main/res/values-uk/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uk/translations.xml @@ -12,6 +12,7 @@ "Введіть ключ відновлення" "Сховище ключів наразі не синхронізовано." "Налаштувати відновлення" + "Ваші чати автоматично резервуються з використанням наскрізного шифрування. Щоб відновити цю резервну копію та зберегти свою цифрову ідентичність у разі втрати доступу до всіх своїх пристроїв, вам знадобиться ключ відновлення." "Відкрийте %1$s на комп\'ютері" "Увійдіть до вашого облікового запису знову" "Коли вас попросять підтвердити пристрій, виберіть %1$s" diff --git a/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml b/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml index c62c4f2af4..60415c2288 100644 --- a/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-pl/translations.xml @@ -1,10 +1,17 @@ - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" - "Dodaj adres pokoju" - "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić żądanie." + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Edytuj adres" + "Przestrzenie, których członkowie mogą dołączyć do pokoju bez zaproszenia." + "Zarządzaj przestrzeniami" + "(Nieznana przestrzeń)" + "Inne przestrzenie, których nie jesteś członkiem" + "Twoje przestrzenie" + "Dodaj adres" + "Każdy w autoryzowanych przestrzeniach może dołączyć, ale wszyscy inni muszą poprosić o dostęp." + "Każdy musi poprosić o dostęp." "Poproś o dołączenie" + "Każdy w %1$s może dołączyć, ale wszyscy pozostali muszą poprosić o dostęp." "Tak, włącz szyfrowanie" "Po włączeniu szyfrowanie pokoju nie może zostać wyłączone, a historia wiadomości będzie widoczna tylko dla członków od momentu, w którym dołączyli lub zostali zaproszeni. Nikt poza członkami pokoju nie będzie mógł czytać wiadomości. Może to wpłynąć na prawidłowe działanie botów lub mostków. @@ -13,23 +20,31 @@ Odradzamy włączanie szyfrowania dla pokoi, które każdy może znaleźć i do "Po włączeniu szyfrowania nie można wyłączyć." "Szyfrowanie" "Włącz szyfrowanie end-to-end" - "Każdy może znaleźć i dołączyć" + "Każdy może dołączyć." "Każdy" - "Tylko osoby z zaproszeniem mogą dołączyć" - "Tylko zaproszenie" - "Dostęp do pokoju" + "Wybierz, którzy członkowie przestrzeni mogą dołączyć do tego pokoju bez zaproszenia. %1$s" + "Zarządzaj przestrzeniami" + "Tylko zaproszone osoby mogą dołączyć" + "Tylko na zaproszenie" + "Dostęp" + "Każdy w autoryzowanych przestrzeniach może dołączyć." + "Każdy w %1$s może dołączyć." + "Członkowie przestrzeni" "Przestrzenie nie są obecnie wspierane" - "Aby pokój był widoczny w katalogu, potrzebny jest adres pokoju." - "Adres pokoju" + "Aby pokój był widoczny w katalogu pokoi publicznych, potrzebny jest adres pokoju." + "Adres" "Zezwól na znalezienie tego pokoju wyszukując %1$s w katalogu pokoi publicznych" + "Zezwól, by inni mogli Cię znaleźć, przeszukując katalog publiczny." "Widoczny w katalogu pokoi publicznych" - "Ktokolwiek" + "Każdy (historia jest publiczna)" + "Zmiany nie zmienią przeszłych wiadomości, tylko nowe. %1$s" "Kto może czytać historię" - "Od momentu kiedy członkowie zostali zaproszeni" - "Członkowie od momentu włączenia tej opcji" + "Członkowie od kiedy zostali zaproszeni" + "Członkowie (cała historia)" "Adresy pokoju umożliwiają łatwe znalezienie i dołączenie do pokojów. Również możesz się zdecydować na upublicznienie Twojego serwera w katalogu pokoi publicznych." "Publikowanie pokoju" - "Widoczność pokoju" + "Adresy pokoi pomagają w znalezieniu i dołączeniu do pokoi i przestrzeni. Umożliwiają również łatwe udostępnianie ich innym." + "Widoczność" "Bezpieczeństwo i prywatność" diff --git a/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml b/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml index f8b96ee6c5..0921887ccb 100644 --- a/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-uk/translations.xml @@ -8,8 +8,10 @@ "Інші простори, учасником яких ви не є" "Ваші простори" "Додати адресу" + "Будь-хто в авторизованих просторах може приєднатися, але всі інші повинні подати запит на доступ." "Усі повинні запитувати доступ." "Запит на приєднання" + "Будь-хто з %1$s може приєднатися, але всі інші повинні подати запит на доступ." "Так, увімкнути шифрування" "Після ввімкнення шифрування кімнати, його неможливо вимкнути, історію повідомлень бачитимуть лише учасники кімнати, яких було запрошено або які приєдналися до кімнати. Ніхто, крім учасників кімнати, не зможе прочитати повідомлення. Це може перешкоджати коректній роботі ботів і мостів. @@ -25,11 +27,14 @@ "Приєднатися можуть лише запрошені люди." "Лише запрошені" "Доступ" + "Долучитися може будь-хто, хто має доступ до авторизованих просторів." "Долучитися може будь-хто з %1$s." + "Учасники простору" "Простори наразі не підтримуються" "Вам знадобиться адреса кімнати, щоб зробити її видимою в каталозі." "Адреса" "Дозвольте, щоб цю кімнату можна було знайти за допомогою пошуку в каталозі загальнодоступних кімнат %1$s " + "Дозвольте знаходити вас за допомогою пошуку в публічному каталозі." "Видима в загальному каталозі" "Будь-хто (загальнодоступна історія)" "Зміни не вплинуть на попередні повідомлення, лише на нові. %1$s" @@ -39,6 +44,7 @@ "Адреси кімнат — це спосіб знайти кімнату та отримати до неї доступ. Це також гарантує, що ви можете легко поділитися своєю кімнатою з іншими. Ви можете опублікувати свою кімнату в каталозі загальнодоступних кімнат вашого домашнього сервера." "Публікація в кімнаті" + "Адреси — це спосіб знаходити кімнати та простори та отримувати до них доступ. Це також гарантує, що ви зможете легко ділитися ними з іншими." "Видимість" "Безпека й приватність" diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt index 10c70d6f7d..882db26f00 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/addroom/AddRoomToSpaceSearchDataSource.kt @@ -15,7 +15,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.recent.getRecentlyVisitedRoomInfoFlow import io.element.android.libraries.matrix.api.roomlist.RoomList import io.element.android.libraries.matrix.api.roomlist.RoomListFilter diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt index 4e1fd34673..e0876c255c 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenter.kt @@ -67,7 +67,7 @@ class LeaveSpacePresenter( .orEmpty() .partition { it.spaceRoom.roomId == leaveSpaceHandle.id } // By default select all rooms that can be left - val otherRoomsExcludingDm = otherRooms.filter { it.spaceRoom.isDirect != true } + val otherRoomsExcludingDm = otherRooms.filter { it.spaceRoom.isDm != true } selectedRoomIds = otherRoomsExcludingDm .filter { it.isLastOwner.not() } .map { it.spaceRoom.roomId } diff --git a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt index c43257b383..20f4918a98 100644 --- a/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt +++ b/features/space/impl/src/main/kotlin/io/element/android/features/space/impl/root/SpaceStateProvider.kt @@ -109,6 +109,7 @@ private fun aSpaceInfo( avatarUrl = null, isPublic = true, isDirect = false, + isDm = false, isEncrypted = false, joinRule = joinRule, isSpace = true, diff --git a/features/space/impl/src/main/res/values-fa/translations.xml b/features/space/impl/src/main/res/values-fa/translations.xml index dcab5c912a..d8f377c0b2 100644 --- a/features/space/impl/src/main/res/values-fa/translations.xml +++ b/features/space/impl/src/main/res/values-fa/translations.xml @@ -8,6 +8,6 @@ "تنها مدیر %1$s هستید" "دیدن اعضا" "ترک فضا" - "نقش‌ها و اجازه‌ها" + "نقش‌ها و مجوزها" "امنیت و محرمانگی" diff --git a/features/space/impl/src/main/res/values-pl/translations.xml b/features/space/impl/src/main/res/values-pl/translations.xml index f1a964c6e3..9c3097b75f 100644 --- a/features/space/impl/src/main/res/values-pl/translations.xml +++ b/features/space/impl/src/main/res/values-pl/translations.xml @@ -9,9 +9,21 @@ "Wybierz pokoje, które chcesz opuścić, a których nie jesteś jedynym administratorem:" "Aby opuścić tę przestrzeń, musisz przypisać do niej innego administratora." + "Jesteś jedynym właścicielem %1$s. Musisz przenieść własność zanim odejdziesz." "Nie zostaniesz usunięty z następujących pokoi, ponieważ jesteś ich jedynym administratorem:" "Opuścić %1$s?" "Jesteś jedynym administratorem %1$s" + "Przenieś własność" + "Pokój" + "Dodanie pokoju nie wpłynie na dostęp do niego. Aby zmienić ustawienia dostępu, przejdź do Ustawienia pokoju > Bezpieczeństwo i prywatność." + "Dodaj swój pierwszy pokój" + "Zobacz członków" + "Usunięcie pokoju nie wpłynie na dostęp do niego. Aby zmienić ustawienia dostępu, przejdź do Ustawienia pokoju > Bezpieczeństwo i prywatność." + + "Usuń %1$d pokój z %2$s" + "Usuń %1$d pokoje z %2$s" + "Usuń %1$d pokoi z %2$s" + "Opuść przestrzeń" "Role i uprawnienia" "Bezpieczeństwo i prywatność" diff --git a/features/space/impl/src/main/res/values-uk/translations.xml b/features/space/impl/src/main/res/values-uk/translations.xml index e124f72826..df4b4fb922 100644 --- a/features/space/impl/src/main/res/values-uk/translations.xml +++ b/features/space/impl/src/main/res/values-uk/translations.xml @@ -2,14 +2,28 @@ "Оберіть власників" "%1$s (Адміністратор)" + + "Залишити %1$d кімнату та простір" + "Залишити %1$d кімнату та простори" + "Залишити %1$d кімнат та просторів" + "Виберіть кімнати, з яких ви хочете вийти, і в них ви не єдиний адміністратор:" "Перш ніж ви зможете вийти, вам потрібно призначити іншого адміністратора для цього простору." + "Ви єдиний власник %1$s. Перш ніж піти, вам потрібно передати право володіння комусь іншому." "Вас не буде видалено з цих кімнат, оскільки ви єдиний адміністратор:" "Вийти з %1$s?" "Ви єдиний адміністратор у %1$s" + "Передача права володіння" "Кімната" + "Додавання кімнати не вплине на доступ до неї. Щоб змінити доступ, перейдіть до «Налаштування кімнати» > «Безпека та конфіденційність»." "Додайте свою першу кімнату" "Переглянути учасників" + "Видалення кімнати не вплине на доступ до неї. Щоб змінити доступ, перейдіть до розділу «Налаштування кімнати» > «Безпека та конфіденційність»." + + "Видалити %1$d кімнату з %2$s" + "Видалити %1$d кімнати з %2$s" + "Видалити %1$d кімнат з %2$s" + "Вийти з простору" "Ролі та дозволи" "Безпека й приватність" diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt index b3b6fc7976..021f52defd 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/leave/LeaveSpacePresenterTest.kt @@ -98,13 +98,13 @@ class LeaveSpacePresenterTest { listOf( aLeaveSpaceRoom(spaceRoom = aSpace), aLeaveSpaceRoom( - spaceRoom = aSpaceRoom(roomId = A_ROOM_ID, isDirect = false) + spaceRoom = aSpaceRoom(roomId = A_ROOM_ID, isDm = false) ), aLeaveSpaceRoom( - spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_2, isDirect = true) + spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_2, isDm = true) ), aLeaveSpaceRoom( - spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_3, isDirect = null) + spaceRoom = aSpaceRoom(roomId = A_ROOM_ID_3, isDm = null) ), ) ) diff --git a/features/verifysession/impl/src/main/res/values-fa/translations.xml b/features/verifysession/impl/src/main/res/values-fa/translations.xml index aa902a94e1..3447c07a7d 100644 --- a/features/verifysession/impl/src/main/res/values-fa/translations.xml +++ b/features/verifysession/impl/src/main/res/values-fa/translations.xml @@ -13,6 +13,7 @@ "يه چيزي درست به نظر نمياد یا زمان درخواست به پایان رسید یا درخواست رد شد." "تأیید تطابق شکلک‌های زیر با شکلک‌های نشان داده شده روی افزارهٔ دیگرتان." "مقایسهٔ شکلک‌ها" + "تأیید کنید که اعداد زیر با اعداد نشان داده شده در جلسه دیگر شما مطابقت دارند." "مقایسهٔ اعداد" "اکنون می‌توانید روی افزارهٔ دیگرتان با امنیت پیام فرستاده و بخوانید." "افزاره تأیید شده" diff --git a/features/verifysession/impl/src/main/res/values-pl/translations.xml b/features/verifysession/impl/src/main/res/values-pl/translations.xml index 92b0572d08..39ce9f6fa3 100644 --- a/features/verifysession/impl/src/main/res/values-pl/translations.xml +++ b/features/verifysession/impl/src/main/res/values-pl/translations.xml @@ -2,8 +2,8 @@ "Nie możesz potwierdzić?" "Utwórz nowy klucz przywracania" - "Zweryfikuj to urządzenie, aby skonfigurować bezpieczne przesyłanie wiadomości." - "Potwierdź, że to Ty" + "Wybierz sposób weryfikacji, aby skonfigurować bezpieczne wiadomości." + "Potwierdź swoją tożsamość cyfrową" "Użyj innego urządzenia" "Użyj klucza przywracania" "Teraz możesz bezpiecznie czytać i wysyłać wiadomości, każdy z kim czatujesz również może ufać temu urządzeniu." @@ -50,5 +50,5 @@ "Po zaakceptowaniu będziesz mógł kontynuować weryfikację." "Zaakceptuj prośbę o rozpoczęcie procesu weryfikacji w innej sesji, aby kontynuować." "Oczekiwanie na zaakceptowanie prośby" - "Wylogowywanie…" + "Usuwam urządzenie…" diff --git a/features/verifysession/impl/src/main/res/values-sk/translations.xml b/features/verifysession/impl/src/main/res/values-sk/translations.xml index 932b8555fc..d4e6f60402 100644 --- a/features/verifysession/impl/src/main/res/values-sk/translations.xml +++ b/features/verifysession/impl/src/main/res/values-sk/translations.xml @@ -50,5 +50,5 @@ "Po prijatí budete môcť pokračovať v overovaní." "Ak chcete pokračovať, prijmite žiadosť o spustenie procesu overenia vo vašej druhej relácii." "Čaká sa na prijatie žiadosti" - "Prebieha odhlasovanie…" + "Odoberanie zariadenia…" diff --git a/features/verifysession/impl/src/main/res/values-uk/translations.xml b/features/verifysession/impl/src/main/res/values-uk/translations.xml index 1967fef383..03fe318d13 100644 --- a/features/verifysession/impl/src/main/res/values-uk/translations.xml +++ b/features/verifysession/impl/src/main/res/values-uk/translations.xml @@ -50,5 +50,5 @@ "Після погодження ви зможете продовжити верифікацію." "Щоб продовжити, прийміть запит на початок процесу верифікації в іншому сеансі." "Очікування на прийняття запиту" - "Вихід…" + "Видалення пристрою…" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 581630c80d..6a69c25787 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ haze = "1.7.2" dependencyAnalysis = "3.10.0" # DI -metro = "0.13.2" +metro = "1.0.0" # Auto service autoservice = "1.1.1" @@ -168,7 +168,7 @@ test_truth = "com.google.truth:truth:1.4.5" test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.22" test_robolectric = "org.robolectric:robolectric:4.16.1" test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" } -test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.8.2" +test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.9.0" test_detekt_api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" } test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" } @@ -178,7 +178,7 @@ test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version # https://github.com/matrix-org/matrix-rust-components-kotlin/commits/main/sdk/sdk-android/src/main/kotlin/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt # All new features should not be implemented in the pull request that upgrades the version, developers should # only fix API breaks and may add some TODOs. -matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.6" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:26.05.13" # Others coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } @@ -214,7 +214,7 @@ maplibre_annotation = "org.maplibre.gl:android-plugin-annotation-v9:3.0.2" opusencoder = "io.element.android:opusencoder:1.2.0" zxing_cpp = "io.github.zxing-cpp:android:3.0.2" google_zxing = "com.google.zxing:core:3.5.4" -google_guava = "com.google.guava:guava:33.5.0-android" +google_guava = "com.google.guava:guava:33.6.0-android" haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" } haze_materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" } @@ -234,7 +234,7 @@ sigpwned_emoji4j = "com.sigpwned:emoji4j-core:16.0.0" metro_runtime = { module = "dev.zacsweers.metro:runtime", version.ref = "metro" } # Element Call -element_call_embedded = "io.element.android:element-call-embedded:0.19.2" +element_call_embedded = "io.element.android:element-call-embedded:0.19.3" # Auto services google_autoservice = { module = "com.google.auto.service:auto-service", version.ref = "autoservice" } @@ -262,13 +262,13 @@ metro = { id = "dev.zacsweers.metro", version.ref = "metro" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } ktlint = "org.jlleitschuh.gradle.ktlint:14.2.0" dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12" -dependencycheck = "org.owasp.dependencycheck:12.2.1" +dependencycheck = "org.owasp.dependencycheck:12.2.2" dependencyanalysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependencyAnalysis" } paparazzi = "app.cash.paparazzi:2.0.0-alpha04" roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } sqldelight = { id = "app.cash.sqldelight", version.ref = "sqldelight" } firebaseAppDistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppDistribution" } -sonarqube = "org.sonarqube:7.2.3.7755" +sonarqube = "org.sonarqube:7.3.0.8198" licensee = "app.cash.licensee:1.14.1" compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } gms_google_services = { id = "com.google.gms.google-services", version = "4.4.4" } diff --git a/libraries/cryptography/api/build.gradle.kts b/libraries/cryptography/api/build.gradle.kts index 9ce26419d8..74fc5f6ecc 100644 --- a/libraries/cryptography/api/build.gradle.kts +++ b/libraries/cryptography/api/build.gradle.kts @@ -13,3 +13,7 @@ plugins { android { namespace = "io.element.android.libraries.cryptography.api" } + +dependencies { + implementation(libs.coroutines.core) +} diff --git a/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt b/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt index ba6c10dbe0..b210664d9f 100644 --- a/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt +++ b/libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyRepository.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.cryptography.api +import kotlinx.coroutines.flow.Flow import javax.crypto.SecretKey /** @@ -15,16 +16,18 @@ import javax.crypto.SecretKey * Implementation should be able to store the generated key securely. */ interface SecretKeyRepository { + fun hasKey(alias: String): Flow + /** * Get or create a secret key for a given alias. * @param alias the alias to use * @param requiresUserAuthentication true if the key should be protected by user authentication */ - fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey + suspend fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey /** * Delete the secret key for a given alias. * @param alias the alias to use */ - fun deleteKey(alias: String) + suspend fun deleteKey(alias: String) } diff --git a/libraries/cryptography/impl/build.gradle.kts b/libraries/cryptography/impl/build.gradle.kts index 454432de6f..3a1f55126e 100644 --- a/libraries/cryptography/impl/build.gradle.kts +++ b/libraries/cryptography/impl/build.gradle.kts @@ -21,6 +21,7 @@ setupDependencyInjection() dependencies { implementation(projects.libraries.di) + implementation(libs.coroutines.core) api(projects.libraries.cryptography.api) testCommonDependencies(libs) diff --git a/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt b/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt index 46572ef047..bcd38695c4 100644 --- a/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt +++ b/libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyRepository.kt @@ -13,11 +13,16 @@ import android.security.keystore.KeyGenParameterSpec import android.security.keystore.KeyProperties import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn import io.element.android.libraries.cryptography.api.AESEncryptionSpecs import io.element.android.libraries.cryptography.api.SecretKeyRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import timber.log.Timber import java.security.KeyStore import java.security.KeyStoreException +import java.util.concurrent.ConcurrentHashMap import javax.crypto.KeyGenerator import javax.crypto.SecretKey @@ -25,13 +30,23 @@ import javax.crypto.SecretKey * Default implementation of [SecretKeyRepository] that uses the Android Keystore to store the keys. * The generated key uses AES algorithm, with a key size of 128 bits, and the GCM block mode. */ +@SingleIn(AppScope::class) @ContributesBinding(AppScope::class) class KeyStoreSecretKeyRepository( private val keyStore: KeyStore, ) : SecretKeyRepository { + private val hasKeyMap = ConcurrentHashMap>() + + @Suppress("RunCatchingNotAllowed") + override fun hasKey(alias: String): Flow { + return hasKeyMap.getOrPut(alias) { + MutableStateFlow(runCatching { keyStore.containsAlias(alias) }.getOrDefault(false)) + }.asStateFlow() + } + // False positive lint issue @SuppressLint("WrongConstant") - override fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { + override suspend fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { val secretKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.SecretKeyEntry) ?.secretKey return if (secretKeyEntry == null) { @@ -46,15 +61,22 @@ class KeyStoreSecretKeyRepository( .setUserAuthenticationRequired(requiresUserAuthentication) .build() generator.init(keyGenSpec) - generator.generateKey() + generator.generateKey().also { + hasKeyMap.getOrPut(alias) { + MutableStateFlow(true) + }.emit(true) + } } else { secretKeyEntry } } - override fun deleteKey(alias: String) { + override suspend fun deleteKey(alias: String) { try { keyStore.deleteEntry(alias) + hasKeyMap.getOrPut(alias) { + MutableStateFlow(false) + }.emit(false) } catch (e: KeyStoreException) { Timber.e(e) } diff --git a/libraries/cryptography/test/build.gradle.kts b/libraries/cryptography/test/build.gradle.kts index eaa621d53a..5cf04a9754 100644 --- a/libraries/cryptography/test/build.gradle.kts +++ b/libraries/cryptography/test/build.gradle.kts @@ -16,4 +16,5 @@ android { dependencies { api(projects.libraries.cryptography.api) + implementation(libs.coroutines.core) } diff --git a/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt b/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt index 0e301553ea..507325f45b 100644 --- a/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt +++ b/libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyRepository.kt @@ -10,20 +10,39 @@ package io.element.android.libraries.cryptography.test import io.element.android.libraries.cryptography.api.AESEncryptionSpecs import io.element.android.libraries.cryptography.api.SecretKeyRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import java.util.concurrent.ConcurrentHashMap import javax.crypto.KeyGenerator import javax.crypto.SecretKey class SimpleSecretKeyRepository : SecretKeyRepository { private var secretKeyForAlias = HashMap() - override fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { + private val hasKeyMap = ConcurrentHashMap>() + + override fun hasKey(alias: String): Flow { + return hasKeyMap.getOrPut(alias) { + MutableStateFlow(false) + }.asStateFlow() + } + + override suspend fun getOrCreateKey(alias: String, requiresUserAuthentication: Boolean): SecretKey { return secretKeyForAlias.getOrPut(alias) { - generateKey() + generateKey().also { + hasKeyMap.getOrPut(alias) { + MutableStateFlow(true) + }.emit(true) + } } } - override fun deleteKey(alias: String) { + override suspend fun deleteKey(alias: String) { secretKeyForAlias.remove(alias) + hasKeyMap.getOrPut(alias) { + MutableStateFlow(false) + }.emit(false) } private fun generateKey(): SecretKey { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt deleted file mode 100644 index f19796e053..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/DmAvatars.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 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 io.element.android.libraries.designsystem.components.avatar - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.drawWithContent -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.BlendMode -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.CompositingStrategy -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.LayoutDirection -import io.element.android.libraries.designsystem.preview.ElementThemedPreview -import io.element.android.libraries.designsystem.preview.PreviewGroup -import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE -import io.element.android.libraries.designsystem.preview.USER_NAME_BOB -import io.element.android.libraries.designsystem.text.toPx -import io.element.android.libraries.testtags.TestTags -import io.element.android.libraries.testtags.testTag -import io.element.android.libraries.ui.strings.CommonStrings - -/** Ratio between the box size (120 on Figma) and the avatar size (75 on Figma). */ -private const val SIZE_RATIO = 1.6f - -/** - * https://www.figma.com/design/A2pAEvTEpJZBiOPUlcMnKi/Settings-%2B-Room-Details-(new)?node-id=1787-56333 - */ -@Composable -fun DmAvatars( - userAvatarData: AvatarData, - otherUserAvatarData: AvatarData, - openAvatarPreview: (url: String) -> Unit, - openOtherAvatarPreview: (url: String) -> Unit, - modifier: Modifier = Modifier, -) { - val boxSize = userAvatarData.size.dp * SIZE_RATIO - val boxSizePx = boxSize.toPx() - val otherAvatarRadius = otherUserAvatarData.size.dp.toPx() / 2 - val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl - Box( - modifier = modifier.size(boxSize), - ) { - // Draw user avatar and cut top end corner - Avatar( - avatarData = userAvatarData, - avatarType = AvatarType.User, - contentDescription = stringResource(CommonStrings.a11y_your_avatar), - modifier = Modifier - .align(Alignment.BottomStart) - .graphicsLayer { - compositingStrategy = CompositingStrategy.Offscreen - } - .drawWithContent { - drawContent() - val xOffset = if (isRtl) { - size.width - boxSizePx + otherAvatarRadius - } else { - boxSizePx - otherAvatarRadius - } - drawCircle( - color = Color.Black, - center = Offset( - x = xOffset, - y = size.height - (boxSizePx - otherAvatarRadius), - ), - radius = otherAvatarRadius / 0.9f, - blendMode = BlendMode.Clear, - ) - } - .clip(CircleShape) - .clickable( - enabled = userAvatarData.url != null, - onClickLabel = stringResource(CommonStrings.action_view), - ) { - userAvatarData.url?.let { openAvatarPreview(it) } - } - ) - // Draw other user avatar - Avatar( - avatarData = otherUserAvatarData, - avatarType = AvatarType.User, - contentDescription = stringResource(CommonStrings.a11y_other_user_avatar), - modifier = Modifier - .align(Alignment.TopEnd) - .clip(CircleShape) - .clickable( - enabled = otherUserAvatarData.url != null, - onClickLabel = stringResource(CommonStrings.action_view), - ) { - otherUserAvatarData.url?.let { openOtherAvatarPreview(it) } - } - .testTag(TestTags.memberDetailAvatar) - ) - } -} - -@Preview(group = PreviewGroup.Avatars) -@Composable -internal fun DmAvatarsPreview() = ElementThemedPreview { - val size = AvatarSize.DmCluster - DmAvatars( - userAvatarData = anAvatarData( - id = "Alice", - name = USER_NAME_ALICE, - size = size, - ), - otherUserAvatarData = anAvatarData( - id = "Bob", - name = USER_NAME_BOB, - size = size, - ), - openAvatarPreview = {}, - openOtherAvatarPreview = {}, - ) -} - -@Preview(group = PreviewGroup.Avatars) -@Composable -internal fun DmAvatarsRtlPreview() { - CompositionLocalProvider( - LocalLayoutDirection provides LayoutDirection.Rtl, - ) { - DmAvatarsPreview() - } -} diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt index b9b6467c92..d234e7b239 100644 --- a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatter.kt @@ -54,6 +54,7 @@ class DefaultRoomLatestEventFormatter( private val roomMembershipContentFormatter: RoomMembershipContentFormatter, private val profileChangeContentFormatter: ProfileChangeContentFormatter, private val stateContentFormatter: StateContentFormatter, + private val rtcNotificationContentFormatter: RtcNotificationContentFormatter, private val permalinkParser: PermalinkParser, ) : RoomLatestEventFormatter { override fun format( @@ -121,7 +122,7 @@ class DefaultRoomLatestEventFormatter( message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is LegacyCallInviteContent -> sp.getString(CommonStrings.common_unsupported_call) - is CallNotifyContent -> sp.getString(CommonStrings.common_call_started) + is CallNotifyContent -> rtcNotificationContentFormatter.format(content, isDmRoom) }?.take(DEFAULT_SAFE_LENGTH) } diff --git a/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt new file mode 100644 index 0000000000..ab3fb9433d --- /dev/null +++ b/libraries/eventformatter/impl/src/main/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatter.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.eventformatter.impl + +import dev.zacsweers.metro.Inject +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.services.toolbox.api.strings.StringProvider + +@Inject +class RtcNotificationContentFormatter( + private val matrixClient: MatrixClient, + private val sp: StringProvider, +) { + fun format( + content: CallNotifyContent, + isDm: Boolean, + ): CharSequence { + return if (isDm) { + val isDeclined = content.declinedBy.isNotEmpty() + val isDeclinedByMe = content.declinedBy.any { matrixClient.isMe(it) } + if (isDeclinedByMe) { + sp.getString(CommonStrings.common_call_you_declined) + } else if (isDeclined) { + sp.getString(CommonStrings.common_call_declined) + } else { + sp.getString(CommonStrings.common_call_started) + } + } else { + sp.getString(CommonStrings.common_call_started) + } + } +} diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt index e1e8717c4c..e0613ed008 100644 --- a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/DefaultRoomLatestEventFormatterTest.kt @@ -74,7 +74,8 @@ class DefaultRoomLatestEventFormatterTest { roomMembershipContentFormatter = RoomMembershipContentFormatter(fakeMatrixClient, stringProvider), profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider), stateContentFormatter = StateContentFormatter(stringProvider), - permalinkParser = FakePermalinkParser(), + rtcNotificationContentFormatter = RtcNotificationContentFormatter(fakeMatrixClient, stringProvider), + permalinkParser = FakePermalinkParser() ) } diff --git a/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt new file mode 100644 index 0000000000..dca34db3cc --- /dev/null +++ b/libraries/eventformatter/impl/src/test/kotlin/io/element/android/libraries/eventformatter/impl/RtcNotificationContentFormatterTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.eventformatter.impl + +import android.content.Context +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.notification.CallIntent +import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.A_USER_ID_3 +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.services.toolbox.impl.strings.AndroidStringProvider +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config +import kotlin.toString + +@Suppress("LargeClass") +@RunWith(RobolectricTestRunner::class) +class RtcNotificationContentFormatterTest { + private lateinit var context: Context + private lateinit var fakeMatrixClient: FakeMatrixClient + private lateinit var formatter: RtcNotificationContentFormatter + + @Before + fun setup() { + context = RuntimeEnvironment.getApplication() as Context + fakeMatrixClient = FakeMatrixClient() + val stringProvider = AndroidStringProvider(context.resources) + formatter = RtcNotificationContentFormatter( + fakeMatrixClient, + stringProvider + ) + } + + @Test + @Config(qualifiers = "en") + fun `Should not display declined info in rooms`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.VIDEO, + declinedBy = listOf(A_USER_ID_2, A_USER_ID_3) + ), + false + ) + val expected = "Call started" + assertThat(result.toString()).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Declined by me variant`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.VIDEO, + declinedBy = listOf(fakeMatrixClient.sessionId) + ), + true + ) + val expected = "You declined a call" + assertThat(result.toString()).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Declined by other variant`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.VIDEO, + declinedBy = listOf(A_USER_ID_2) + ), + true + ) + val expected = "Call declined" + assertThat(result.toString()).isEqualTo(expected) + } + + @Test + @Config(qualifiers = "en") + fun `Call started in DM`() { + val result = formatter.format( + CallNotifyContent( + CallIntent.AUDIO, + declinedBy = listOf() + ), + true + ) + val expected = "Call started" + assertThat(result.toString()).isEqualTo(expected) + } +} diff --git a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt index cdda66579b..ab7dcb9960 100644 --- a/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt +++ b/libraries/featureflag/api/src/main/kotlin/io/element/android/libraries/featureflag/api/FeatureFlags.kt @@ -102,7 +102,7 @@ enum class FeatureFlags( ), AllowBlackTheme( key = "feature.allow_black_theme", - title = "Allow black theme", + title = "Black theme", description = "Allow selecting the black appearance theme for battery saving on OLED.", defaultValue = { false }, isFinished = false, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 59fd7a4940..bd7b1399e1 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.room.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.spaces.SpaceService @@ -67,6 +68,7 @@ interface MatrixClient { val sessionCoroutineScope: CoroutineScope val ignoredUsersFlow: StateFlow> val roomMembershipObserver: RoomMembershipObserver + val ownBeaconInfoUpdates: Flow suspend fun getJoinedRoom(roomId: RoomId): JoinedRoom? suspend fun getRoom(roomId: RoomId): BaseRoom? suspend fun findDM(userId: UserId): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt index ac3b0c8e3a..f515ce8c32 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/analytics/ViewRoomExt.kt @@ -19,7 +19,7 @@ fun BaseRoom.toAnalyticsViewRoom( val activeSpace = selectedSpace?.toActiveSpace() ?: ViewRoom.ActiveSpace.Home return ViewRoom( - isDM = info().isDirect, + isDM = info().isDm, isSpace = info().isSpace, trigger = trigger, activeSpace = activeSpace, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt index 4d8ce8afb4..7ae1ca4886 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notificationsettings/NotificationSettingsService.kt @@ -21,7 +21,7 @@ interface NotificationSettingsService { val notificationSettingsChangeFlow: SharedFlow suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result - suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result + suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isDM: Boolean): Result suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result suspend fun muteRoom(roomId: RoomId): Result diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt index 589f88e9fd..f7f4924d5a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/BaseRoom.kt @@ -61,13 +61,12 @@ interface BaseRoom : Closeable { */ fun info(): RoomInfo = roomInfoFlow.value - fun predecessorRoom(): PredecessorRoom? - /** - * A one-to-one is a room with exactly 2 members. - * See [the Matrix spec](https://spec.matrix.org/latest/client-server-api/#default-underride-rules). + * Returns whether the [BaseRoom] is a DM, with an updated state from the latest [RoomInfo]. */ - val isOneToOne: Boolean get() = info().activeMembersCount == 2L + fun isDm() = roomInfoFlow.value.isDm + + fun predecessorRoom(): PredecessorRoom? /** * Try to load the room members and update the membersFlow. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt index 5247e402a6..b9ed8d61b1 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomInfo.kt @@ -29,6 +29,7 @@ data class RoomInfo( val avatarUrl: String?, val isPublic: Boolean?, val isDirect: Boolean, + val isDm: Boolean, val isEncrypted: Boolean?, val joinRule: JoinRule?, val isSpace: Boolean, diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt deleted file mode 100644 index f33319e2ee..0000000000 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheck.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 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 io.element.android.libraries.matrix.api.room - -import kotlinx.coroutines.flow.first - -/** - * Returns whether the room with the provided info is a DM. - * A DM is a room with at most 2 active members (one of them may have left). - * - * @param isDirect true if the room is direct - * @param activeMembersCount the number of active members in the room (joined or invited) - */ -fun isDm(isDirect: Boolean, activeMembersCount: Int): Boolean { - return isDirect && activeMembersCount <= 2 -} - -/** - * Returns whether the [BaseRoom] is a DM, with an updated state from the latest [RoomInfo]. - */ -suspend fun BaseRoom.isDm() = roomInfoFlow.first().isDm - -/** - * Returns whether the [RoomInfo] is from a DM. - */ -val RoomInfo.isDm get() = isDm(isDirect, activeMembersCount.toInt()) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt index 0b3d7071c8..abf685a38b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMember.kt @@ -22,6 +22,7 @@ data class RoomMember( val isIgnored: Boolean, val role: Role, val membershipChangeReason: String?, + val isServiceMember: Boolean, ) { /** * Role of the RoomMember, based on its [powerLevel]. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt index 1c35fab7d0..2c93fa94f0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/RoomMembersState.kt @@ -40,5 +40,5 @@ fun RoomMembersState.activeRoomMembers(): List { fun RoomMembersState.getDirectRoomMember(roomInfo: RoomInfo, sessionId: SessionId): RoomMember? { return roomMembers() ?.takeIf { roomInfo.isDm } - ?.find { it.userId != sessionId && it.membership.isActive() } + ?.find { !it.isServiceMember && it.userId != sessionId && it.membership.isActive() } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt new file mode 100644 index 0000000000..358dcd98d1 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconId.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.location + +import io.element.android.libraries.matrix.api.core.EventId + +typealias BeaconId = EventId diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt new file mode 100644 index 0000000000..0b7e9b0f44 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/BeaconInfoUpdate.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.location + +import io.element.android.libraries.matrix.api.core.RoomId + +data class BeaconInfoUpdate( + val roomId: RoomId, + val beaconId: BeaconId, + val isLive: Boolean, +) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt new file mode 100644 index 0000000000..9b53603042 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationException.kt @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.api.room.location + +sealed class LiveLocationException(message: String?) : Exception(message) { + class NotLive : LiveLocationException("The beacon event has expired.") + class Network : LiveLocationException("Network error") + class Other(val exception: Exception) : LiveLocationException(exception.message) +} diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt index 3f9c108dc7..4d8bc4638a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/location/LiveLocationShare.kt @@ -21,6 +21,8 @@ data class LiveLocationShare( val startTimestamp: Long, /** The timestamp when location sharing ends, in milliseconds. */ val endTimestamp: Long, + /** The event id from the beacon info. */ + val beaconId: BeaconId ) data class LastLocation( diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt index 6db326c854..3441a4be3a 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/recent/RecentDirectRoom.kt @@ -12,7 +12,6 @@ import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.CurrentUserMembership -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.toMatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.coroutines.flow.Flow diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt index aca093eab6..10ca376105 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomSummary.kt @@ -21,5 +21,5 @@ data class RoomSummary( is LatestEventValue.Remote -> latestEvent.timestamp is LatestEventValue.RoomInvite -> latestEvent.timestamp } - val isOneToOne get() = info.activeMembersCount == 2L + val isDm = info.isDm } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt index 6a72577760..e22b0a5c9c 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/spaces/SpaceRoom.kt @@ -38,6 +38,7 @@ data class SpaceRoom( */ val via: ImmutableList, val isDirect: Boolean?, + val isDm: Boolean?, ) { val isSpace = roomType == RoomType.Space diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt index d91d404a0b..f323b316f7 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/timeline/item/event/EventContent.kt @@ -119,7 +119,8 @@ data class LiveLocationContent( data object LegacyCallInviteContent : EventContent data class CallNotifyContent( - val callIntent: CallIntent + val callIntent: CallIntent, + val declinedBy: List ) : EventContent data object UnknownContent : EventContent diff --git a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt b/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt deleted file mode 100644 index 1461d28fd9..0000000000 --- a/libraries/matrix/api/src/test/kotlin/io/element/android/libraries/matrix/api/room/RoomIsDmCheckTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2024, 2025 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 io.element.android.libraries.matrix.api.room - -import com.google.common.truth.Truth.assertThat -import org.junit.Test - -class RoomIsDmCheckTest { - @Test - fun `a room is a DM only if it has at most 2 members and is direct`() { - val isDirect = true - val activeMembersCount = 2 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isTrue() - } - - @Test - fun `a room can be a DM if it has also a single active user`() { - val isDirect = true - val activeMembersCount = 1 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isTrue() - } - - @Test - fun `a room is not a DM if it's not direct`() { - val isDirect = false - val activeMembersCount = 2 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isFalse() - } - - @Test - fun `a room is not a DM if it has more than 2 active users`() { - val isDirect = true - val activeMembersCount = 3 - - val isDm = isDm(isDirect, activeMembersCount) - - assertThat(isDm).isFalse() - } -} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 5a1dc9da4b..05e52605dc 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -70,6 +70,7 @@ import io.element.android.libraries.matrix.impl.room.RustRoomFactory import io.element.android.libraries.matrix.impl.room.TimelineEventFilterFactory import io.element.android.libraries.matrix.impl.room.history.map import io.element.android.libraries.matrix.impl.room.join.map +import io.element.android.libraries.matrix.impl.room.location.map import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper import io.element.android.libraries.matrix.impl.roomdirectory.RustRoomDirectoryService import io.element.android.libraries.matrix.impl.roomdirectory.map @@ -113,6 +114,8 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout import org.matrix.rustcomponents.sdk.AuthData import org.matrix.rustcomponents.sdk.AuthDataPasswordDetails +import org.matrix.rustcomponents.sdk.BeaconInfoListener +import org.matrix.rustcomponents.sdk.BeaconInfoUpdate import org.matrix.rustcomponents.sdk.Client import org.matrix.rustcomponents.sdk.ClientException import org.matrix.rustcomponents.sdk.IgnoredUsersListener @@ -207,6 +210,15 @@ class RustMatrixClient( analyticsService = analyticsService, ) + override val ownBeaconInfoUpdates = mxCallbackFlow { + val listener = object : BeaconInfoListener { + override fun onUpdate(update: BeaconInfoUpdate) { + trySend(update.map()) + } + } + innerClient.subscribeToOwnBeaconInfoUpdates(listener) + } + override val sessionVerificationService = RustSessionVerificationService( client = innerClient, isSyncServiceReady = syncService.syncState.map { it == SyncState.Running }, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 0bf26091c2..9a573a59c1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -41,6 +41,7 @@ import org.matrix.rustcomponents.sdk.SlidingSyncVersion import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder import org.matrix.rustcomponents.sdk.use import timber.log.Timber +import uniffi.matrix_sdk_base.DmRoomDefinition import uniffi.matrix_sdk_base.MediaRetentionPolicy import uniffi.matrix_sdk_crypto.CollectStrategy import uniffi.matrix_sdk_crypto.DecryptionSettings @@ -169,6 +170,7 @@ class RustMatrixClientFactory( ) .enableShareHistoryOnInvite(true) .threadsEnabled(featureFlagService.isFeatureEnabled(FeatureFlags.Threads), threadSubscriptions = false) + .dmRoomDefinition(DmRoomDefinition.TWO_MEMBERS) .requestConfig( RequestConfig( timeout = 30_000uL, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt index 263ce15bd3..8a0a246c22 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt @@ -11,7 +11,6 @@ package io.element.android.libraries.matrix.impl.analytics import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.libraries.matrix.api.room.BaseRoom import io.element.android.libraries.matrix.api.room.RoomInfo -import io.element.android.libraries.matrix.api.room.isDm import kotlinx.coroutines.flow.first private fun Long.toAnalyticsRoomSize(): JoinedRoom.RoomSize { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt index f1996dd942..bfb49d6ceb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt @@ -17,7 +17,6 @@ import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.impl.room.join.map import io.element.android.services.toolbox.api.systemclock.SystemClock import org.matrix.rustcomponents.sdk.NotificationEvent @@ -37,10 +36,6 @@ class NotificationMapper( ): Result { return runCatchingExceptions { notificationItem.use { item -> - val isDm = isDm( - isDirect = item.roomInfo.isDirect, - activeMembersCount = item.roomInfo.joinedMembersCount.toInt(), - ) val timestamp = item.timestamp() ?: clock.epochMillis() NotificationData( sessionId = sessionId, @@ -50,10 +45,10 @@ class NotificationMapper( senderAvatarUrl = item.senderInfo.avatarUrl, senderDisplayName = item.senderInfo.displayName, senderIsNameAmbiguous = item.senderInfo.isNameAmbiguous, - roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { isDm }, + roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { item.roomInfo.isDm }, roomDisplayName = item.roomInfo.displayName, isDirect = item.roomInfo.isDirect, - isDm = isDm, + isDm = item.roomInfo.isDm, isSpace = item.roomInfo.isSpace, isEncrypted = item.roomInfo.isEncrypted.orFalse(), isNoisy = item.isNoisy.orFalse(), diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt index 7da0f14d14..6a88e5051b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsService.kt @@ -62,11 +62,11 @@ class RustNotificationSettingsService( override suspend fun setDefaultRoomNotificationMode( isEncrypted: Boolean, mode: RoomNotificationMode, - isOneToOne: Boolean + isDM: Boolean ): Result = withContext(dispatchers.io) { runCatchingExceptions { try { - notificationSettings.await().setDefaultRoomNotificationMode(isEncrypted, isOneToOne, mode.let(RoomNotificationSettingsMapper::mapMode)) + notificationSettings.await().setDefaultRoomNotificationMode(isEncrypted, isDM, mode.let(RoomNotificationSettingsMapper::mapMode)) } catch (exception: NotificationSettingsException.RuleNotFound) { // `setDefaultRoomNotificationMode` updates multiple rules including unstable rules (e.g. the polls push rules defined in the MSC3930) // since production home servers may not have these rules yet, we drop the RuleNotFound error diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt index 87ef0815ce..e75091eadc 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/JoinedRustRoom.kt @@ -45,6 +45,7 @@ import io.element.android.libraries.matrix.impl.room.history.map import io.element.android.libraries.matrix.impl.room.join.map import io.element.android.libraries.matrix.impl.room.knock.RustKnockRequest import io.element.android.libraries.matrix.impl.room.location.liveLocationSharesFlow +import io.element.android.libraries.matrix.impl.room.location.map import io.element.android.libraries.matrix.impl.room.location.timedByExpiry import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.room.threads.RustThreadsListService @@ -72,6 +73,7 @@ import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.DateDividerMode import org.matrix.rustcomponents.sdk.IdentityStatusChangeListener import org.matrix.rustcomponents.sdk.KnockRequestsListener +import org.matrix.rustcomponents.sdk.LiveLocationException import org.matrix.rustcomponents.sdk.RoomMessageEventMessageType import org.matrix.rustcomponents.sdk.RoomSendQueueUpdate import org.matrix.rustcomponents.sdk.SendQueueListener @@ -346,7 +348,7 @@ class JoinedRustRoom( roomNotificationSettingsStateFlow.value = RoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings) runCatchingExceptions { val isEncrypted = roomInfoFlow.value.isEncrypted ?: getUpdatedIsEncrypted().getOrThrow() - notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow() + notificationSettingsService.getRoomNotificationSettings(roomId = roomId, isEncrypted = isEncrypted, isOneToOne = isDm()).getOrThrow() }.map { roomNotificationSettingsStateFlow.value = RoomNotificationSettingsState.Ready(it) }.onFailure { @@ -525,12 +527,22 @@ class JoinedRustRoom( override suspend fun stopLiveLocationShare(): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.stopLiveLocationShare() + }.mapFailure { throwable -> + when (throwable) { + is LiveLocationException -> throwable.map() + else -> throwable + } } } override suspend fun sendLiveLocation(geoUri: String): Result = withContext(roomDispatcher) { runCatchingExceptions { innerRoom.sendLiveLocation(geoUri) + }.mapFailure { throwable -> + when (throwable) { + is LiveLocationException -> throwable.map() + else -> throwable + } } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt index 668cfc46df..4c8da1aca7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExt.kt @@ -18,7 +18,7 @@ import org.matrix.rustcomponents.sdk.RoomInfo */ fun RoomInfo.elementHeroes(): List { return heroes - .takeIf { isDirect && activeMembersCount.toLong() == 2L } + .takeIf { isDm } ?.takeIf { it.size == 1 } ?.map { it.map() } .orEmpty() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt index deca0f8ee6..0e9aadc65b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapper.kt @@ -43,6 +43,7 @@ class RoomInfoMapper { avatarUrl = it.avatarUrl, isPublic = it.isPublic, isDirect = it.isDirect, + isDm = it.isDm, isEncrypted = when (it.encryptionState) { EncryptionState.ENCRYPTED -> true EncryptionState.NOT_ENCRYPTED -> false diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt index e73bed084e..0551891a6d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustBaseRoom.kt @@ -23,7 +23,6 @@ import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMembersState import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.draft.ComposerDraft -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevelsValues import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom @@ -119,7 +118,7 @@ class RustBaseRoom( innerRoom.membersNoSync().use { members -> members.nextChunk(members.len()) ?.map(RoomMemberMapper::map) - ?.firstOrNull { roomMember -> roomMember.userId != sessionId && roomMember.membership.isActive() } + ?.firstOrNull { roomMember -> !roomMember.isServiceMember && roomMember.userId != sessionId && roomMember.membership.isActive() } } } else { null diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt new file mode 100644 index 0000000000..44be305c02 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/BeaconInfoUpdates.kt @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.location + +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate +import org.matrix.rustcomponents.sdk.BeaconInfoUpdate as RustBeaconInfoUpdate + +fun RustBeaconInfoUpdate.map(): BeaconInfoUpdate { + return BeaconInfoUpdate( + roomId = RoomId(roomId), + beaconId = EventId(eventId), + isLive = live + ) +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt new file mode 100644 index 0000000000..b10f5cd41c --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationException.kt @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.room.location + +import io.element.android.libraries.matrix.api.room.location.LiveLocationException +import org.matrix.rustcomponents.sdk.LiveLocationException as RustLiveLocationException + +fun RustLiveLocationException.map(): LiveLocationException { + return when (this) { + is RustLiveLocationException.Network -> LiveLocationException.Network() + is RustLiveLocationException.NotLive -> LiveLocationException.NotLive() + else -> LiveLocationException.Other(this) + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt index 1a341d0dc2..8e8181539f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt @@ -7,6 +7,7 @@ package io.element.android.libraries.matrix.impl.room.location +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.location.LastLocation import io.element.android.libraries.matrix.api.room.location.LiveLocationShare @@ -41,9 +42,9 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { } } return callbackFlow { - val liveLocationShares = liveLocationsObserver() + val observer = liveLocationsObserver() val shares: MutableList = ArrayList() - val taskHandle = liveLocationShares.subscribe(object : LiveLocationsListener { + val taskHandle = observer.subscribe(object : LiveLocationsListener { override fun onUpdate(updates: List) { for (update in updates) { shares.applyUpdate(update) @@ -53,13 +54,14 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { }) awaitClose { taskHandle.cancelAndDestroy() - liveLocationShares.destroy() + observer.destroy() } }.buffer(Channel.UNLIMITED) } private fun RustLiveLocationShare.into(): LiveLocationShare { return LiveLocationShare( + beaconId = EventId(beaconId), userId = UserId(userId), lastLocation = lastLocation?.let { LastLocation( @@ -69,6 +71,6 @@ private fun RustLiveLocationShare.into(): LiveLocationShare { ) }, startTimestamp = startTs.toLong(), - endTimestamp = (startTs + timeout).toLong() + endTimestamp = (startTs + timeout).toLong(), ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt index 447fa427a6..33ecb74ff3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapper.kt @@ -28,7 +28,8 @@ object RoomMemberMapper { powerLevel = powerLevel, isIgnored = roomMember.isIgnored, role = mapRole(roomMember.suggestedRoleForPowerLevel, powerLevel), - membershipChangeReason = roomMember.membershipChangeReason + membershipChangeReason = roomMember.membershipChangeReason, + isServiceMember = roomMember.isServiceMember, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt index f83cd648a6..cd729d0df1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/spaces/SpaceRoomMapper.kt @@ -36,6 +36,7 @@ class SpaceRoomMapper { worldReadable = spaceRoom.worldReadable.orFalse(), via = spaceRoom.via.toImmutableList(), isDirect = spaceRoom.isDirect, + isDm = spaceRoom.isDm, ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt index 7b398529a0..5da4be408d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt @@ -20,7 +20,6 @@ import io.element.android.libraries.matrix.api.media.VideoInfo import io.element.android.libraries.matrix.api.poll.PollKind import io.element.android.libraries.matrix.api.room.IntentionalMention import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MsgType diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index edfe9a3543..fa671bc546 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -153,7 +153,8 @@ class TimelineEventContentMapper( CallIntent.AUDIO } else { CallIntent.VIDEO - } + }, + declinedBy = it.declinedBy.map(::UserId) ) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt index 68adfe00a2..3c094f3581 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedExtKtTest.kt @@ -43,6 +43,19 @@ class JoinedExtKtTest { @Test fun `test isDirect parameter mapping`() = runTest { assertThat(aRoom(isDirect = true).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = false, + roomSize = JoinedRoom.RoomSize.One, + trigger = null + ) + ) + } + + @Test + fun `test isDm parameter mapping`() = runTest { + assertThat(aRoom(isDm = true).toAnalyticsJoinedRoom(null)) .isEqualTo( JoinedRoom( isDM = true, @@ -80,12 +93,13 @@ class JoinedExtKtTest { } private fun aRoom( + isDm: Boolean = false, isDirect: Boolean = false, isSpace: Boolean = false, joinedMemberCount: Long = 0 ): FakeBaseRoom { return FakeBaseRoom().apply { - givenRoomInfo(aRoomInfo(isDirect = isDirect, isSpace = isSpace, joinedMembersCount = joinedMemberCount)) + givenRoomInfo(aRoomInfo(isDm = isDm, isDirect = isDirect, isSpace = isSpace, joinedMembersCount = joinedMemberCount)) } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt index 82984c480d..63ad77238b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt @@ -67,6 +67,7 @@ internal fun aRustNotificationRoomInfo( joinedMembersCount: ULong = 2u, isEncrypted: Boolean? = true, isDirect: Boolean = false, + isDm: Boolean = false, joinRule: JoinRule? = null, isSpace: Boolean = false, serviceMembers: List = emptyList(), @@ -79,6 +80,7 @@ internal fun aRustNotificationRoomInfo( joinedMembersCount = joinedMembersCount, isEncrypted = isEncrypted, isDirect = isDirect, + isDm = isDm, joinRule = joinRule, isSpace = isSpace, serviceMembers = serviceMembers.map { it.value }, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt index 50115055c2..2eb46eddaf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SpaceRoom.kt @@ -19,6 +19,7 @@ import org.matrix.rustcomponents.sdk.SpaceRoom internal fun aRustSpaceRoom( roomId: RoomId = A_ROOM_ID, isDirect: Boolean = false, + isDm: Boolean = false, canonicalAlias: String? = null, rawName: String? = null, displayName: String = "", @@ -35,6 +36,7 @@ internal fun aRustSpaceRoom( ) = SpaceRoom( roomId = roomId.value, isDirect = isDirect, + isDm = isDm, canonicalAlias = canonicalAlias, rawName = rawName, displayName = displayName, @@ -48,5 +50,5 @@ internal fun aRustSpaceRoom( childrenCount = childrenCount, state = state, heroes = heroes, - via = emptyList() + via = emptyList(), ) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt index 59d82487b9..623fe9a8cf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeFfiClientBuilder.kt @@ -17,6 +17,7 @@ import org.matrix.rustcomponents.sdk.RequestConfig import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder import org.matrix.rustcomponents.sdk.SqliteStoreBuilder import uniffi.matrix_sdk.BackupDownloadStrategy +import uniffi.matrix_sdk_base.DmRoomDefinition import uniffi.matrix_sdk_crypto.CollectStrategy import uniffi.matrix_sdk_crypto.DecryptionSettings @@ -47,5 +48,6 @@ class FakeFfiClientBuilder( override fun sqliteStore(config: SqliteStoreBuilder): ClientBuilder = this override fun inMemoryStore(): ClientBuilder = this override fun crossProcessLockConfig(crossProcessLockConfig: CrossProcessLockConfig): ClientBuilder = this + override fun dmRoomDefinition(dmRoomDefinition: DmRoomDefinition): ClientBuilder = this override suspend fun build() = buildResult() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index 86a50c3926..dd91595359 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -20,8 +20,7 @@ class RoomInfoExtTest { @Test fun `get non empty element Heroes`() { val result = aRustRoomInfo( - isDirect = true, - activeMembersCount = 2uL, + isDm = true, heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEqualTo( @@ -38,8 +37,7 @@ class RoomInfoExtTest { @Test fun `too many heroes and element Heroes is empty`() { val result = aRustRoomInfo( - isDirect = true, - activeMembersCount = 2uL, + isDm = true, heroes = listOf(aRustRoomHero(), aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() @@ -48,18 +46,7 @@ class RoomInfoExtTest { @Test fun `not direct and element Heroes is empty`() { val result = aRustRoomInfo( - isDirect = false, - activeMembersCount = 2uL, - heroes = listOf(aRustRoomHero()) - ).elementHeroes() - assertThat(result).isEmpty() - } - - @Test - fun `too many members and element Heroes is empty`() { - val result = aRustRoomInfo( - isDirect = true, - activeMembersCount = 3uL, + isDm = false, heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt index ab353bc0f5..56b480d97f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoMapperTest.kt @@ -86,6 +86,7 @@ class RoomInfoMapperTest { privilegedCreatorsRole = true, isLowPriority = true, activeRoomCallConsensusIntent = RtcCallIntentConsensus.Full(RtcCallIntent.AUDIO), + isDm = true, ) ) ).isEqualTo( @@ -136,6 +137,7 @@ class RoomInfoMapperTest { privilegedCreatorRole = true, isLowPriority = true, activeCallIntentConsensus = CallIntentConsensus.Full(CallIntent.AUDIO), + isDm = true, ) ) } @@ -181,6 +183,7 @@ class RoomInfoMapperTest { privilegedCreatorsRole = true, isLowPriority = true, activeRoomCallConsensusIntent = RtcCallIntentConsensus.None, + isDm = false, ) ) ).isEqualTo( @@ -225,6 +228,7 @@ class RoomInfoMapperTest { privilegedCreatorRole = true, isLowPriority = true, activeCallIntentConsensus = CallIntentConsensus.None, + isDm = false, ) ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt index 41627396ad..ba91dae468 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt @@ -11,6 +11,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.test.room.location.aLiveLocationShare import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.emptyFlow @@ -24,9 +25,9 @@ class TimedLiveLocationSharesFlowTest { @Test fun `it keeps emitting shares for subsequent expiries without upstream changes`() = runTest { val shares = listOf( - aLiveLocationShare(userId = "@alice:server", endTimestamp = 1_000), - aLiveLocationShare(userId = "@bob:server", endTimestamp = 2_000), - aLiveLocationShare(userId = "@carol:server", endTimestamp = 3_000), + aLiveLocationShare(userId = UserId("@alice:server"), endTimestamp = 1_000), + aLiveLocationShare(userId = UserId("@bob:server"), endTimestamp = 2_000), + aLiveLocationShare(userId = UserId("@carol:server"), endTimestamp = 3_000), ) flowOf(shares) @@ -56,8 +57,8 @@ class TimedLiveLocationSharesFlowTest { @Test fun `it does not double-emit when a share is already expired on receipt`() = runTest { val shares = listOf( - aLiveLocationShare(userId = "@alice:server", endTimestamp = 500), - aLiveLocationShare(userId = "@bob:server", endTimestamp = 2_000), + aLiveLocationShare(userId = UserId("@alice:server"), endTimestamp = 500), + aLiveLocationShare(userId = UserId("@bob:server"), endTimestamp = 2_000), ) flowOf(shares) @@ -81,8 +82,8 @@ class TimedLiveLocationSharesFlowTest { val upstream = MutableSharedFlow>(extraBufferCapacity = 1) val initialShares = listOf(aLiveLocationShare(endTimestamp = 10_000)) val updatedShares = listOf( - aLiveLocationShare(userId = "@alice:server", endTimestamp = 10_000), - aLiveLocationShare(userId = "@bob:server", endTimestamp = 6_000), + aLiveLocationShare(userId = UserId("@alice:server"), endTimestamp = 10_000), + aLiveLocationShare(userId = UserId("@bob:server"), endTimestamp = 6_000), ) upstream @@ -133,15 +134,3 @@ class TimedLiveLocationSharesFlowTest { } } } - -private fun aLiveLocationShare( - userId: String = "@user:server", - endTimestamp: Long, -): LiveLocationShare { - return LiveLocationShare( - userId = UserId(userId), - lastLocation = null, - startTimestamp = 0L, - endTimestamp = endTimestamp, - ) -} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 26bc0af8c1..af28dc37e4 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -34,6 +34,7 @@ import io.element.android.libraries.matrix.api.room.NotJoinedRoom import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias +import io.element.android.libraries.matrix.api.room.location.BeaconInfoUpdate import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.spaces.SpaceService @@ -107,6 +108,7 @@ class FakeMatrixClient( private val canReportRoomLambda: () -> Boolean = { false }, private val isLivekitRtcSupportedLambda: () -> Boolean = { false }, override val ignoredUsersFlow: StateFlow> = MutableStateFlow(persistentListOf()), + override val ownBeaconInfoUpdates: Flow = emptyFlow(), private val getMaxUploadSizeResult: () -> Result = { lambdaError() }, private val getJoinedRoomIdsResult: () -> Result> = { Result.success(emptySet()) }, private val getRecentEmojisLambda: () -> Result> = { Result.success(emptyList()) }, diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt index 564cd231b2..f7970e7971 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notificationsettings/FakeNotificationSettingsService.kt @@ -70,12 +70,12 @@ class FakeNotificationSettingsService( } } - override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isOneToOne: Boolean): Result { + override suspend fun setDefaultRoomNotificationMode(isEncrypted: Boolean, mode: RoomNotificationMode, isDM: Boolean): Result { val error = setDefaultNotificationModeError if (error != null) { return Result.failure(error) } - if (isOneToOne) { + if (isDM) { if (isEncrypted) { defaultEncryptedOneToOneRoomNotificationMode = mode } else { diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt index d1cd340641..b4425ddd4b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeJoinedRoom.kt @@ -89,7 +89,7 @@ class FakeJoinedRoom( private val updateJoinRuleResult: (JoinRule) -> Result = { lambdaError() }, private val setSendQueueEnabledResult: (Boolean) -> Unit = { _: Boolean -> }, private val liveLocationSharesFlow: Flow> = MutableStateFlow(emptyList()), - private val startLiveLocationShareResult: (Long) -> Result = { lambdaError() }, + private val startLiveLocationShareResult: (Long) -> Result = { lambdaError() }, private val stopLiveLocationShareResult: () -> Result = { lambdaError() }, private val sendLiveLocationResult: (String) -> Result = { lambdaError() }, ) : JoinedRoom, BaseRoom by baseRoom { @@ -134,7 +134,11 @@ class FakeJoinedRoom( } override suspend fun updateRoomNotificationSettings(): Result = simulateLongTask { - val notificationSettings = roomNotificationSettingsService.getRoomNotificationSettings(roomId, info().isEncrypted.orFalse(), isOneToOne).getOrThrow() + val notificationSettings = roomNotificationSettingsService.getRoomNotificationSettings( + roomId = roomId, + isEncrypted = info().isEncrypted.orFalse(), + isOneToOne = isDm(), + ).getOrThrow() (roomNotificationSettingsStateFlow as MutableStateFlow).value = RoomNotificationSettingsState.Ready(notificationSettings) return Result.success(Unit) } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt index c7faaba627..c15330e9dc 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomInfoFixture.kt @@ -71,6 +71,7 @@ fun aRoomInfo( privilegedCreatorRole: Boolean = false, isLowPriority: Boolean = false, activeCallIntentConsensus: CallIntentConsensus = CallIntentConsensus.None, + isDm: Boolean = false, ) = RoomInfo( id = id, name = name, @@ -109,4 +110,5 @@ fun aRoomInfo( privilegedCreatorRole = privilegedCreatorRole, isLowPriority = isLowPriority, activeCallIntentConsensus = activeCallIntentConsensus, + isDm = isDm, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt index f6bc0c5ec2..33a1b68ba3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomMemberFixture.kt @@ -23,6 +23,7 @@ fun aRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -33,6 +34,7 @@ fun aRoomMember( isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomMemberList() = persistentListOf( diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt index afe4c88f5a..32635a7eea 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/RoomSummaryFixture.kt @@ -120,6 +120,7 @@ fun aRoomSummary( privilegedCreatorRole = privilegedCreatorRole, isLowPriority = isLowPriority, activeCallIntentConsensus = activeCallIntentConsensus, + isDm = false, ), latestEvent = latestEvent, ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt new file mode 100644 index 0000000000..23730c8886 --- /dev/null +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/location/LiveLocationFixture.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.matrix.test.room.location + +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.location.AssetType +import io.element.android.libraries.matrix.api.room.location.LastLocation +import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_USER_ID + +fun aLiveLocationShare( + beaconId: EventId = AN_EVENT_ID, + userId: UserId = A_USER_ID, + geoUri: String = "geo:48.8584,2.2945", + timestamp: Long = 0L, + startTimestamp: Long = 0L, + endTimestamp: Long = Long.MAX_VALUE, + assetType: AssetType = AssetType.SENDER, +): LiveLocationShare { + return LiveLocationShare( + beaconId = beaconId, + userId = userId, + lastLocation = LastLocation( + geoUri = geoUri, + timestamp = timestamp, + assetType = assetType, + ), + startTimestamp = startTimestamp, + endTimestamp = endTimestamp, + ) +} diff --git a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt index e67e630e97..ef654a4cf7 100644 --- a/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt +++ b/libraries/matrixmedia/impl/src/main/kotlin/io/element/android/libraries/matrix/ui/media/ImageLoaderFactories.kt @@ -16,7 +16,6 @@ import coil3.gif.GifDecoder import coil3.network.okhttp.OkHttpNetworkFetcherFactory import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import io.element.android.libraries.di.annotations.ApplicationContext import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import okhttp3.OkHttpClient @@ -29,7 +28,7 @@ interface ImageLoaderFactory { @ContributesBinding(AppScope::class) class DefaultImageLoaderFactory( @ApplicationContext private val context: Context, - private val okHttpClient: Provider, + private val okHttpClient: () -> OkHttpClient, ) : ImageLoaderFactory { private val okHttpNetworkFetcherFactory = OkHttpNetworkFetcherFactory( callFactory = { diff --git a/libraries/matrixui/src/main/res/values-it/translations.xml b/libraries/matrixui/src/main/res/values-it/translations.xml index 439d61337e..913c45867c 100644 --- a/libraries/matrixui/src/main/res/values-it/translations.xml +++ b/libraries/matrixui/src/main/res/values-it/translations.xml @@ -3,5 +3,7 @@ "Invia invito" "Vuoi iniziare una conversazione con%1$s?" "Inviare invito?" + "Al momento non hai alcuna conversazione con questa persona. Conferma l\'invito prima di continuare." + "Vuoi avviare una conversazione con questo nuovo contatto?" "%1$s (%2$s) ti ha invitato" diff --git a/libraries/matrixui/src/main/res/values-pl/translations.xml b/libraries/matrixui/src/main/res/values-pl/translations.xml index caa2c0e07d..bd31d7edb4 100644 --- a/libraries/matrixui/src/main/res/values-pl/translations.xml +++ b/libraries/matrixui/src/main/res/values-pl/translations.xml @@ -3,5 +3,7 @@ "Wyślij zaproszenie" "Czy chcesz rozpocząć czat z %1$s?" "Wysłać zaproszenie?" + "Obecnie nie posiadasz żadnych czatów z tą osobą. Potwierdź zaproszenie, zanim przejdziesz dalej." + "Rozpocząć czat z nowym kontaktem?" "%1$s (%2$s) zaprosił Cię" diff --git a/libraries/matrixui/src/main/res/values-uk/translations.xml b/libraries/matrixui/src/main/res/values-uk/translations.xml index 324bb96086..4d2063fbd2 100644 --- a/libraries/matrixui/src/main/res/values-uk/translations.xml +++ b/libraries/matrixui/src/main/res/values-uk/translations.xml @@ -3,5 +3,7 @@ "Надіслати запрошення" "Хочете розпочати бесіду з %1$s?" "Надіслати запрошення?" + "Наразі у вас немає чатів із цим користувачем. Підтвердьте запрошення, перш ніж продовжити." + "Розпочати чат із цим новим контактом?" "%1$s (%2$s) запрошує вас" diff --git a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt index 816ac0967e..737fff34ee 100644 --- a/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt +++ b/libraries/matrixui/src/test/kotlin/io/element/android/libraries/matrix/ui/room/RoomMembersTest.kt @@ -30,13 +30,10 @@ class RoomMembersTest { private val roomMember3 = aRoomMember(A_USER_ID_3) @Test - fun `getDirectRoomMember emits other member for encrypted DM with 2 joined members`() = runTest { + fun `getDirectRoomMember emits other member for encrypted DM`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo( - isDirect = true, - joinedMembersCount = 2, - ) + initialRoomInfo = aRoomInfo(isDm = true, isEncrypted = true) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -51,7 +48,7 @@ class RoomMembersTest { fun `getDirectRoomMember emit null if the room is not a dm`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(isDirect = false) + initialRoomInfo = aRoomInfo(isDm = false) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -66,10 +63,7 @@ class RoomMembersTest { fun `getDirectRoomMember emits other member even if the room is not encrypted`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo( - isDirect = true, - activeMembersCount = 2, - ) + initialRoomInfo = aRoomInfo(isDm = true) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -80,42 +74,11 @@ class RoomMembersTest { } } - @Test - fun `getDirectRoomMember emit null if the room has only 1 member`() = runTest { - val joinedRoom = FakeBaseRoom( - sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(isDirect = true) - ) - moleculeFlow(RecompositionMode.Immediate) { - joinedRoom.getDirectRoomMember( - RoomMembersState.Ready(persistentListOf(roomMember1)) - ) - }.test { - assertThat(awaitItem().value).isNull() - } - } - - @Test - fun `getDirectRoomMember emit null if the room has only 3 members`() = runTest { - val joinedRoom = FakeBaseRoom( - sessionId = A_USER_ID, - ).apply { - givenRoomInfo(aRoomInfo(isDirect = true, activeMembersCount = 3L)) - } - moleculeFlow(RecompositionMode.Immediate) { - joinedRoom.getDirectRoomMember( - RoomMembersState.Ready(persistentListOf(roomMember1, roomMember2, roomMember3)) - ) - }.test { - assertThat(awaitItem().value).isNull() - } - } - @Test fun `getDirectRoomMember emit null if the other member is not active`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo(isDirect = true), + initialRoomInfo = aRoomInfo(isDm = true), ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( @@ -135,10 +98,7 @@ class RoomMembersTest { fun `getDirectRoomMember emit the other member if there are 2 active members`() = runTest { val joinedRoom = FakeBaseRoom( sessionId = A_USER_ID, - initialRoomInfo = aRoomInfo( - isDirect = true, - activeMembersCount = 2, - ) + initialRoomInfo = aRoomInfo(isDm = true) ) moleculeFlow(RecompositionMode.Immediate) { joinedRoom.getDirectRoomMember( diff --git a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt index 74b479dc8c..fedf376a60 100644 --- a/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt +++ b/libraries/mediaviewer/api/src/main/kotlin/io/element/android/libraries/mediaviewer/api/MediaInfo.kt @@ -17,6 +17,7 @@ import kotlinx.parcelize.Parcelize data class MediaInfo( val filename: String, val caption: String?, + val formattedCaption: CharSequence? = null, val mimeType: String, val fileSize: Long?, val formattedFileSize: String, @@ -33,6 +34,7 @@ data class MediaInfo( fun anImageMediaInfo( senderId: UserId? = UserId("@alice:server.org"), caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -40,6 +42,7 @@ fun anImageMediaInfo( filename = "an image file.jpg", fileSize = 4 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Jpeg, formattedFileSize = "4MB", fileExtension = "jpg", @@ -54,6 +57,7 @@ fun anImageMediaInfo( fun aVideoMediaInfo( caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -62,6 +66,7 @@ fun aVideoMediaInfo( filename = "a video file.mp4", fileSize = 14 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Mp4, formattedFileSize = "14MB", fileExtension = "mp4", @@ -77,6 +82,7 @@ fun aVideoMediaInfo( fun aPdfMediaInfo( filename: String = "a pdf file.pdf", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -84,6 +90,7 @@ fun aPdfMediaInfo( filename = filename, fileSize = 23 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Pdf, formattedFileSize = "23MB", fileExtension = "pdf", @@ -105,6 +112,7 @@ fun anApkMediaInfo( filename = "an apk file.apk", fileSize = 50 * 1024 * 1024, caption = null, + formattedCaption = null, mimeType = MimeTypes.Apk, formattedFileSize = "50MB", fileExtension = "apk", @@ -120,6 +128,7 @@ fun anApkMediaInfo( fun anAudioMediaInfo( filename: String = "an audio file.mp3", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -129,6 +138,7 @@ fun anAudioMediaInfo( filename = filename, fileSize = 7 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Mp3, formattedFileSize = "7MB", fileExtension = "mp3", @@ -144,6 +154,7 @@ fun anAudioMediaInfo( fun aVoiceMediaInfo( filename: String = "a voice file.ogg", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -153,6 +164,7 @@ fun aVoiceMediaInfo( filename = filename, fileSize = 3 * 1024 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.Ogg, formattedFileSize = "3MB", fileExtension = "ogg", @@ -168,6 +180,7 @@ fun aVoiceMediaInfo( fun aTxtMediaInfo( filename: String = "a text file.txt", caption: String? = null, + formattedCaption: CharSequence? = null, senderName: String? = null, dateSent: String? = null, dateSentFull: String? = null, @@ -175,6 +188,7 @@ fun aTxtMediaInfo( filename = filename, fileSize = 2 * 1024, caption = caption, + formattedCaption = formattedCaption, mimeType = MimeTypes.PlainText, formattedFileSize = "2kB", fileExtension = "txt", diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index 9c2342ecd9..cd1579d50d 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -25,6 +25,9 @@ android { setupDependencyInjection() dependencies { + implementation(libs.matrix.richtexteditor.compose) + implementation(libs.matrix.richtexteditor) + implementation(projects.libraries.textcomposer.impl) implementation(libs.coroutines.core) implementation(libs.coil.compose) implementation(libs.androidx.media3.exoplayer) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt index e1e112ecfa..138f6382d2 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPoint.kt @@ -32,6 +32,7 @@ class DefaultMediaViewerEntryPoint : MediaViewerEntryPoint { filename = filename, fileSize = null, caption = null, + formattedCaption = null, mimeType = mimeType, formattedFileSize = "", fileExtension = "", diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt index 379c70f960..898a29aa7a 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/EventItemFactory.kt @@ -98,6 +98,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -118,6 +119,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -139,6 +141,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -160,6 +163,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -181,6 +185,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), @@ -202,6 +207,7 @@ class EventItemFactory( filename = type.filename, fileSize = type.info?.size, caption = type.caption, + formattedCaption = type.formattedCaption?.body, mimeType = type.info?.mimetype.orEmpty(), formattedFileSize = type.info?.size?.let { fileSizeFormatter.format(it) }.orEmpty(), fileExtension = fileExtensionExtractor.extractFromName(type.filename), diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt index 05cbe40f36..83e8a17cf4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/AndroidLocalMediaFactory.kt @@ -97,6 +97,7 @@ class AndroidLocalMediaFactory( filename = fileName, fileSize = fileSize, caption = caption, + formattedCaption = null, formattedFileSize = calculatedFormattedFileSize, fileExtension = fileExtension, senderId = senderId, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt index cb1da7b9b2..8cc14d6445 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerStateProvider.kt @@ -195,6 +195,86 @@ open class MediaViewerStateProvider : PreviewParameterProvider ) ) }, + anImageMediaInfo( + senderName = "Bob", + dateSent = "22 NOV, 2024", + formattedCaption = "This is a bold caption", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Charlie", + dateSent = "23 NOV, 2024", + formattedCaption = "This is an italic caption", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Diana", + dateSent = "24 NOV, 2024", + formattedCaption = "This is a code caption", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Eve", + dateSent = "25 NOV, 2024", + formattedCaption = "
This is a quote caption
", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, + anImageMediaInfo( + senderName = "Frank", + dateSent = "26 NOV, 2024", + formattedCaption = "This caption has bold, italic, and code formatting.", + ).let { + aMediaViewerState( + listOf( + aMediaViewerPageData( + downloadedMedia = AsyncData.Success( + LocalMedia(Uri.EMPTY, it) + ), + mediaInfo = it, + ) + ) + ) + }, ) } diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt index 3738f6643b..8bc5088187 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerView.kt @@ -31,8 +31,11 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -59,10 +62,12 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import androidx.core.text.toSpannable import coil3.compose.AsyncImage import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.viewfolder.api.TextFileViewer +import io.element.android.libraries.androidutils.text.safeLinkify import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.audio.api.AudioFocus import io.element.android.libraries.core.mimetype.MimeTypes.isMimeTypeVideo @@ -91,7 +96,9 @@ import io.element.android.libraries.mediaviewer.impl.local.LocalMediaView import io.element.android.libraries.mediaviewer.impl.local.PlayableState import io.element.android.libraries.mediaviewer.impl.local.rememberLocalMediaViewState import io.element.android.libraries.mediaviewer.impl.util.bgCanvasWithTransparency +import io.element.android.libraries.textcomposer.ElementRichTextEditorStyle import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.wysiwyg.compose.EditorStyledText import kotlinx.coroutines.delay import me.saket.telephoto.zoomable.OverzoomEffect import me.saket.telephoto.zoomable.ZoomSpec @@ -242,6 +249,7 @@ fun MediaViewerView( MediaViewerBottomBar( showDivider = dataForPage.mediaInfo.mimeType.isMimeTypeVideo(), caption = dataForPage.mediaInfo.caption, + formattedCaption = dataForPage.mediaInfo.formattedCaption, onHeightChange = { bottomPaddingInPixels = it }, ) } @@ -545,6 +553,7 @@ private fun MediaViewerTopBar( @Composable private fun MediaViewerBottomBar( caption: String?, + formattedCaption: CharSequence?, showDivider: Boolean, onHeightChange: (Int) -> Unit, modifier: Modifier = Modifier, @@ -557,7 +566,7 @@ private fun MediaViewerBottomBar( onHeightChange(it.height) }, ) { - if (caption != null) { + if (caption != null || formattedCaption != null) { if (showDivider) { HorizontalDivider() } @@ -568,15 +577,28 @@ private fun MediaViewerBottomBar( .fillMaxWidth() .heightIn(max = if (hasCompactHeightWindowSize()) maxCaptionHeightLandscape else maxCaptionHeightPortrait), ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - .verticalScroll(scrollState) - .navigationBarsPadding(), - text = caption, - style = ElementTheme.typography.fontBodyLgRegular, - ) + val textToRender = when { + formattedCaption != null -> formattedCaption + caption != null -> caption.safeLinkify().toSpannable() + else -> null + } + if (textToRender != null) { + CompositionLocalProvider( + LocalContentColor provides ElementTheme.colors.textPrimary, + LocalTextStyle provides ElementTheme.typography.fontBodyLgRegular + ) { + EditorStyledText( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + .verticalScroll(scrollState) + .navigationBarsPadding(), + text = textToRender, + style = ElementRichTextEditorStyle.textStyle(), + releaseOnDetach = false, + ) + } + } if (showBottomShadow) { Box( modifier = Modifier diff --git a/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml index 72701194fc..913329122e 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-it/translations.xml @@ -16,6 +16,7 @@ "Nome del file" "Nessun altro file da mostrare" "Non ci sono più contenuti multimediali da mostrare" + "Informazioni sul file" "Caricato da" "Caricato il" diff --git a/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml index c398123873..a1f7a3bdf9 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-pl/translations.xml @@ -16,6 +16,7 @@ "Nazwa pliku" "Brak plików do pokazania" "Brak mediów do pokazania" + "Informacje pliku" "Przesłane przez" "Przesłane w dniu" diff --git a/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml b/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml index 45e1e1703b..ddc316fb4b 100644 --- a/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml +++ b/libraries/mediaviewer/impl/src/main/res/values-uk/translations.xml @@ -16,6 +16,7 @@ "Назва файлу" "Більше немає файлів для показу" "Більше немає медіа для показу" + "Інформація про файл" "Вивантажено користувачем" "Вивантажено" diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt index 6602f475eb..ab3ffa98c7 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/DefaultEventItemFactoryTest.kt @@ -62,7 +62,7 @@ class DefaultEventItemFactoryTest { fun `create check all null cases`() { val factory = createEventItemFactory() val contents = listOf( - CallNotifyContent(callIntent = CallIntent.VIDEO), + CallNotifyContent(callIntent = CallIntent.VIDEO, emptyList()), FailedToParseMessageLikeContent("", ""), FailedToParseStateContent("", "", ""), LegacyCallInviteContent, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt index 528fc1da70..88aefb842c 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt @@ -235,6 +235,7 @@ class TimelineMediaGalleryDataSourceTest { filename = "body.jpg", fileSize = 888L, caption = "body.jpg caption", + formattedCaption = "formatted", mimeType = MimeTypes.Jpeg, formattedFileSize = "888 Bytes", fileExtension = "jpg", diff --git a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt index faa27fd0e3..8dbee232df 100644 --- a/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt +++ b/libraries/mediaviewer/test/src/main/kotlin/io/element/android/libraries/mediaviewer/test/FakeLocalMediaFactory.kt @@ -41,6 +41,7 @@ class FakeLocalMediaFactory( filename = safeName, fileSize = null, caption = null, + formattedCaption = null, mimeType = mimeType ?: fallbackMimeType, formattedFileSize = formattedFileSize ?: fallbackFileSize, fileExtension = fileExtensionExtractor.extractFromName(safeName), diff --git a/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt b/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt index 88240c3d65..39a54dca61 100644 --- a/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt +++ b/libraries/network/src/main/kotlin/io/element/android/libraries/network/RetrofitFactory.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.network import dev.zacsweers.metro.Inject -import dev.zacsweers.metro.Provider import io.element.android.libraries.androidutils.json.JsonProvider import io.element.android.libraries.core.uri.ensureTrailingSlash import okhttp3.MediaType.Companion.toMediaType @@ -19,8 +18,8 @@ import retrofit2.converter.kotlinx.serialization.asConverterFactory @Inject class RetrofitFactory( - private val okHttpClient: Provider, - private val json: Provider, + private val okHttpClient: () -> OkHttpClient, + private val json: () -> JsonProvider, ) { fun create(baseUrl: String): Retrofit = Retrofit.Builder() .baseUrl(baseUrl.ensureTrailingSlash()) diff --git a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt index 476658946a..df8dc8acc9 100644 --- a/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt +++ b/libraries/preferences/api/src/main/kotlin/io/element/android/libraries/preferences/api/store/AppPreferencesStore.kt @@ -23,6 +23,9 @@ interface AppPreferencesStore { suspend fun setTheme(theme: String) fun getThemeFlow(): Flow + suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) + fun getLiveLocationMinimumDistanceInMetersUpdateFlow(): Flow + @Deprecated("Use MediaPreviewService instead. Kept only for migration.") suspend fun setHideInviteAvatars(hide: Boolean?) @Deprecated("Use MediaPreviewService instead. Kept only for migration.") diff --git a/libraries/preferences/impl/build.gradle.kts b/libraries/preferences/impl/build.gradle.kts index 0478d303ea..73327a69a2 100644 --- a/libraries/preferences/impl/build.gradle.kts +++ b/libraries/preferences/impl/build.gradle.kts @@ -1,4 +1,5 @@ import extension.setupDependencyInjection +import extension.testCommonDependencies /* * Copyright (c) 2025 Element Creations Ltd. @@ -26,4 +27,6 @@ dependencies { implementation(projects.libraries.core) implementation(projects.libraries.matrix.api) implementation(projects.libraries.sessionStorage.api) + testCommonDependencies(libs) + testImplementation(projects.libraries.preferences.test) } diff --git a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt index 6856f8bdb6..44260461da 100644 --- a/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt +++ b/libraries/preferences/impl/src/main/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStore.kt @@ -10,6 +10,7 @@ package io.element.android.libraries.preferences.impl.store import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding @@ -28,6 +29,7 @@ private val customElementCallBaseUrlKey = stringPreferencesKey("elementCallBaseU private val themeKey = stringPreferencesKey("theme") private val hideInviteAvatarsKey = booleanPreferencesKey("hideInviteAvatars") private val timelineMediaPreviewValueKey = stringPreferencesKey("timelineMediaPreviewValue") +private val liveLocationMinimumDistanceUpdateKey = intPreferencesKey("liveLocationMinimumDistanceUpdate") private val logLevelKey = stringPreferencesKey("logLevel") private val traceLogPacksKey = stringPreferencesKey("traceLogPacks") @@ -79,6 +81,18 @@ class DefaultAppPreferencesStore( } } + override suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) { + store.edit { prefs -> + prefs[liveLocationMinimumDistanceUpdateKey] = value + } + } + + override fun getLiveLocationMinimumDistanceInMetersUpdateFlow(): Flow { + return store.data.map { prefs -> + prefs[liveLocationMinimumDistanceUpdateKey] ?: 10 + } + } + @Deprecated("Use MediaPreviewService instead. Kept only for migration.") override fun getHideInviteAvatarsFlow(): Flow { return store.data.map { prefs -> diff --git a/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt b/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt new file mode 100644 index 0000000000..c52d1648ac --- /dev/null +++ b/libraries/preferences/impl/src/test/kotlin/io/element/android/libraries/preferences/impl/store/DefaultAppPreferencesStoreTest.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.preferences.impl.store + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.meta.BuildMeta +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultAppPreferencesStoreTest { + private val buildMeta = BuildMeta( + buildType = BuildType.DEBUG, + isDebuggable = true, + applicationName = "Element X", + productionApplicationName = "Element", + desktopApplicationName = "Element Desktop", + applicationId = "io.element.android", + isEnterpriseBuild = false, + lowPrivacyLoggingEnabled = false, + versionName = "1.0.0", + versionCode = 1, + gitRevision = "test", + gitBranchName = "test", + flavorDescription = "test", + flavorShortDescription = "test", + ) + + @Test + fun `live location minimum distance defaults to 10`() = runTest { + val store = DefaultAppPreferencesStore( + buildMeta = buildMeta, + preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + ) + + assertThat(store.getLiveLocationMinimumDistanceInMetersUpdateFlow().first()).isEqualTo(10) + } + + @Test + fun `live location minimum distance persists updates`() = runTest { + val store = DefaultAppPreferencesStore( + buildMeta = buildMeta, + preferenceDataStoreFactory = FakePreferenceDataStoreFactory(), + ) + + store.setLiveLocationMinimumDistanceInMetersUpdate(25) + + assertThat(store.getLiveLocationMinimumDistanceInMetersUpdateFlow().first()).isEqualTo(25) + } +} diff --git a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt index 6e7d22a568..152de12e99 100644 --- a/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt +++ b/libraries/preferences/test/src/main/kotlin/io/element/android/libraries/preferences/test/InMemoryAppPreferencesStore.kt @@ -21,12 +21,14 @@ class InMemoryAppPreferencesStore( hideInviteAvatars: Boolean? = null, timelineMediaPreviewValue: MediaPreviewValue? = null, theme: String? = null, + liveLocationMinimumDistanceUpdate: Int = 10, logLevel: LogLevel = LogLevel.INFO, traceLockPacks: Set = emptySet(), ) : AppPreferencesStore { private val isDeveloperModeEnabled = MutableStateFlow(isDeveloperModeEnabled) private val customElementCallBaseUrl = MutableStateFlow(customElementCallBaseUrl) private val theme = MutableStateFlow(theme) + private val liveLocationMinimumDistanceUpdate = MutableStateFlow(liveLocationMinimumDistanceUpdate) private val logLevel = MutableStateFlow(logLevel) private val tracingLogPacks = MutableStateFlow(traceLockPacks) private val hideInviteAvatars = MutableStateFlow(hideInviteAvatars) @@ -56,6 +58,14 @@ class InMemoryAppPreferencesStore( return theme } + override suspend fun setLiveLocationMinimumDistanceInMetersUpdate(value: Int) { + liveLocationMinimumDistanceUpdate.value = value + } + + override fun getLiveLocationMinimumDistanceInMetersUpdateFlow(): Flow { + return liveLocationMinimumDistanceUpdate + } + @Deprecated("Use MediaPreviewService instead. Kept only for migration.") override fun getHideInviteAvatarsFlow(): Flow { return hideInviteAvatars diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt index 42fc527bb2..49f77ddefb 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/RoomMemberFixture.kt @@ -33,6 +33,7 @@ fun aRoomMember( isIgnored: Boolean = false, role: RoomMember.Role = RoomMember.Role.User, membershipChangeReason: String? = null, + isServiceMember: Boolean = false, ) = RoomMember( userId = userId, displayName = displayName, @@ -43,6 +44,7 @@ fun aRoomMember( isIgnored = isIgnored, role = role, membershipChangeReason = membershipChangeReason, + isServiceMember = isServiceMember, ) fun aRoomMemberList() = persistentListOf( diff --git a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt index 68825540a4..6f86789693 100644 --- a/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt +++ b/libraries/previewutils/src/main/kotlin/io/element/android/libraries/previewutils/room/SpaceRoomFixture.kt @@ -34,6 +34,7 @@ fun aSpaceRoom( topic: String? = null, worldReadable: Boolean = false, isDirect: Boolean? = null, + isDm: Boolean? = null, via: List = emptyList(), ) = SpaceRoom( rawName = rawName, @@ -51,5 +52,6 @@ fun aSpaceRoom( topic = topic, worldReadable = worldReadable, via = via.toImmutableList(), - isDirect = isDirect + isDirect = isDirect, + isDm = isDm, ) diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt index ff7119b647..367052eaad 100644 --- a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/notifications/NotificationIdProvider.kt @@ -53,4 +53,5 @@ object NotificationIdProvider { enum class ForegroundServiceType { INCOMING_CALL, ONGOING_CALL, + LIVE_LOCATION, } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt index eb08a25c6a..cb9ef8c82d 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiverHandler.kt @@ -19,7 +19,6 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.room.CreateTimelineParams import io.element.android.libraries.matrix.api.room.JoinedRoom -import io.element.android.libraries.matrix.api.room.isDm import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.preferences.api.store.SessionPreferencesStoreFactory diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt index 2b3587837e..b1c90a374a 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/FetchPushForegroundService.kt @@ -13,17 +13,14 @@ import android.content.pm.ServiceInfo import android.os.Build import android.os.IBinder import android.os.PowerManager +import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat import androidx.core.app.ServiceCompat -import dev.zacsweers.metro.Inject -import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.extensions.runCatchingExceptions import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.push.impl.di.PushBindings -import io.element.android.libraries.push.impl.notifications.channels.NotificationChannels import io.element.android.libraries.ui.strings.CommonStrings -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.MainScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import timber.log.Timber @@ -34,6 +31,12 @@ private const val NOTIFICATION_ID = 1001 // This kind of foreground service can only last up to 3 minutes before onTimeout is called private val wakelockTimeout = 3.minutes.inWholeMilliseconds +// The channel ID to use for the notification of the foreground service. +private const val CHANNEL_ID = "fetch_push_notification_channel" + +// The tag to use for the wakelock, this is used for debugging purposes and should be unique to this service. +private const val WAKELOCK_TAG = "FetchPushService:WakeLock" + /** * Foreground service used to ensure the device stays awake while we handle the pushes and schedule and run the work to fetch the notification content. */ @@ -42,28 +45,35 @@ class FetchPushForegroundService : Service() { return null } - @Inject lateinit var notificationChannels: NotificationChannels - @Inject @AppCoroutineScope lateinit var coroutineScope: CoroutineScope - private val wakelock: PowerManager.WakeLock by lazy { val powerManager = getSystemService(POWER_SERVICE) as PowerManager - powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FetchPushService:WakeLock").apply { + powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG).apply { setReferenceCounted(false) } } private var isOnForeground = false + private fun ensureNotificationChannelExists() { + NotificationManagerCompat.from(this).createNotificationChannelsCompat( + listOf( + NotificationChannelCompat.Builder(CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_LOW) + .setName(getString(CommonStrings.common_fetching_notifications_title_android).ifEmpty { "Syncing notifications…" }) + .setVibrationEnabled(false) + .setSound(null, null) + .build() + ) + ) + } + override fun onCreate() { - Timber.d("Creating FetchPushForegroundService") + Timber.i("Creating FetchPushForegroundService to handle incoming push, acquiring wakelock for up to $wakelockTimeout ms") + ensureNotificationChannelExists() - bindings().inject(this) - - Timber.d("Starting FetchPushForegroundService with wakelock timeout of $wakelockTimeout ms") // Start the foreground service as soon as possible - val notificationCompat = NotificationCompat.Builder(this, notificationChannels.getSilentChannelId()) + val notificationCompat = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(CommonDrawables.ic_notification) - .setContentTitle(getString(CommonStrings.common_android_fetching_notifications_title)) + .setContentTitle(getString(CommonStrings.common_fetching_notifications_title_android).ifEmpty { "Syncing notifications…" }) .setProgress(0, 0, true) .setVibrate(longArrayOf(0)) .setSound(null) @@ -103,7 +113,7 @@ class FetchPushForegroundService : Service() { // The timeout is not automatic before Android 15, so we need to schedule it ourselves if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { - coroutineScope.launch { + MainScope().launch { delay(wakelockTimeout) onTimeoutAction(calledByTheSystem = false) } @@ -112,13 +122,18 @@ class FetchPushForegroundService : Service() { return START_NOT_STICKY } - override fun stopService(intent: Intent?): Boolean { - if (isOnForeground) { - wakelock.release() - ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) - } + override fun onDestroy() { + super.onDestroy() - return super.stopService(intent) + if (isOnForeground) { + Timber.i("Destroying FetchPushForegroundService, releasing wakelock and stopping foreground") + if (wakelock.isHeld) { + wakelock.release() + } + ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) + } else { + Timber.w("Destroying FetchPushForegroundService that was not running in foreground, this is unexpected") + } } override fun onTimeout(startId: Int) { @@ -127,9 +142,9 @@ class FetchPushForegroundService : Service() { } private fun onTimeoutAction(calledByTheSystem: Boolean) { - Timber.d("onTimeoutAction, calledByTheSystem: $calledByTheSystem, isOnForeground: $isOnForeground") + Timber.w("onTimeoutAction, calledByTheSystem: $calledByTheSystem, isOnForeground: $isOnForeground") if (isOnForeground) { - Timber.d("Wakelock timeout reached, stopping FetchPushForegroundService") + Timber.w("Wakelock timeout reached, stopping FetchPushForegroundService") stopSelf() } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt index c18a0015aa..cefbd31515 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationsWorker.kt @@ -153,7 +153,7 @@ class FetchPendingNotificationsWorker( private suspend fun checkNetworkConnection(requests: List): Result? { val networkTimeoutSpans = requests.mapNotNull { request -> - val parent = analyticsService.getLongRunningTransaction(AnalyticsLongRunningTransaction.PushToWorkManager(request.eventId)) + val parent = analyticsService.getLongRunningTransaction(AnalyticsLongRunningTransaction.PushToNotification(request.eventId)) parent?.startChild("Waiting for network connectivity", "await_network") } diff --git a/libraries/push/impl/src/main/res/values-pl/translations.xml b/libraries/push/impl/src/main/res/values-pl/translations.xml index b9ae289507..d8a4077d05 100644 --- a/libraries/push/impl/src/main/res/values-pl/translations.xml +++ b/libraries/push/impl/src/main/res/values-pl/translations.xml @@ -15,7 +15,14 @@ "%d powiadomienia" "%d powiadomień" + "Nie udało się zarejestrować dystrybutora powiadomień Push, przez co nie będziesz już otrzymywać powiadomień. Sprawdź ustawienia powiadomień aplikacji i status dystrybutora powiadomień Push." "Masz nowe wiadomości." + + "Masz %d nową wiadomość." + "Masz %d nowe wiadomości." + "Masz %d nowych wiadomości." + + "📞 Połączenie przychodzące" "📹 Połączenie przychodzące" "** Nie udało się wysłać - proszę otworzyć pokój" "Dołącz" @@ -41,12 +48,15 @@ "%1$s zaprosił Cię do pokoju" "Ja" "%1$s wspomniał lub odpowiedział" + "Zaprosił Cię do dołączenia do przestrzeni" + "%1$s zaprosił Cię do dołączenia do przestrzeni" "Wyświetlasz powiadomienie! Kliknij mnie!" + "Wątek w %1$s" "%1$s: %2$s" "%1$s: %2$s %3$s" "%d nieprzeczytana wiadomość" - "%d nieprzeczytane wiadomość" + "%d nieprzeczytane wiadomości" "%d nieprzeczytanych wiadomości" "%1$s i %2$s" diff --git a/libraries/push/impl/src/main/res/values-uk/translations.xml b/libraries/push/impl/src/main/res/values-uk/translations.xml index d3aee22165..9c5f74605f 100644 --- a/libraries/push/impl/src/main/res/values-uk/translations.xml +++ b/libraries/push/impl/src/main/res/values-uk/translations.xml @@ -15,7 +15,14 @@ "%d сповіщення" "%d сповіщень" + "Розподільник сповіщень UnifiedPush не вдалося зареєструвати, тому ви більше не отримуватимете сповіщень. Перевірте налаштування сповіщень у додатку та статус розподільника push-сповіщень." "У вас є нові повідомлення." + + "У вас %d нове повідомлення." + "У вас %d нових повідомлення." + "У вас %d нових повідомлень." + + "📞 Вхідний дзвінок" "📹 Вхідний виклик" "** Не вдалося надіслати - відкрийте кімнату" "Доєднатися" @@ -41,6 +48,7 @@ "%1$s запросив вас приєднатися до кімнати" "Я" "%1$s згадували або відповідали" + "Вас запросили приєднатися до простору" "%1$s запрошує вас приєднатися до простору" "Ви переглядаєте сповіщення! Натисніть тут!" "Гілка в %1$s" @@ -62,11 +70,18 @@ "Фонова синхронізація" "Сервіси Google" "Не знайдено дійсних сервісів Google Play. Сповіщення можуть не працювати належним чином." + "Перевірка заблокованих користувачів" "Переглянути заблокованих користувачів" "Немає заблокованих користувачів" + + "Ви заблокували %1$d користувача. Ви не отримуватимете сповіщення для цього користувача." + "Ви заблокували %1$d користувачів. Ви не отримуватимете сповіщення для цих користувачів." + "Ви заблокували %1$d користувачів. Ви не отримуватимете сповіщення для цих користувачів." + "Заблоковані користувачі" "Отримує назву поточного постачальника." "Постачальників push-сповіщень не вибрано." + "Поточний провайдер push-повідомлень: %1$s та поточний дистриб\'ютор: %2$s. Але дистриб\'ютор %3$s не знайдено. Можливо, додаток було видалено?" "Поточний постачальник push-сповіщень: %1$s, але дистриб\'юторів не налаштовано." "Поточний постачальник: %1$s." "Поточний постачальник push-сповіщень: %1$s (%2$s)" diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt index fdf5cc5f1b..a7c3a6837b 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/observer/FakeSessionObserver.kt @@ -10,12 +10,13 @@ package io.element.android.libraries.sessionstorage.test.observer import io.element.android.libraries.sessionstorage.api.observer.SessionListener import io.element.android.libraries.sessionstorage.api.observer.SessionObserver +import java.util.concurrent.CopyOnWriteArraySet class FakeSessionObserver : SessionObserver { - private val _listeners = mutableListOf() + private val _listeners = CopyOnWriteArraySet() val listeners: List - get() = _listeners + get() = _listeners.toList() override fun addListener(listener: SessionListener) { _listeners.add(listener) diff --git a/libraries/ui-strings/src/main/res/values-be/translations.xml b/libraries/ui-strings/src/main/res/values-be/translations.xml index 4011474193..f550ce1075 100644 --- a/libraries/ui-strings/src/main/res/values-be/translations.xml +++ b/libraries/ui-strings/src/main/res/values-be/translations.xml @@ -170,7 +170,6 @@ "Аўтарскае права" "Стварэнне пакоя…" "Выйшаў з пакоя" - "Цёмная" "Памылка расшыфроўкі" "Параметры распрацоўшчыка" "Прамы чат" @@ -197,7 +196,6 @@ "Усталяваць APK" "Гэты Matrix ID не знойдзены, таму запрашэнне можа быць не атрымана." "Пакінуць пакой" - "Светлая" "Спасылка скапіравана ў буфер абмену" "Загрузка…" @@ -244,7 +242,6 @@ "Ключ аднаўлення" "Абнаўленне…" "Адказвае на %1$s" - "Паведаміць пра памылку" "Паведаміць аб праблеме" "Скарга прынята" "Рэдактар фарматаванага тэксту" @@ -273,7 +270,6 @@ "Поспех" "Прапановы" "Сінхранізацыя" - "Сістэмная" "Тэкст" "Паведамленні трэціх асоб" "Гутарка" diff --git a/libraries/ui-strings/src/main/res/values-bg/translations.xml b/libraries/ui-strings/src/main/res/values-bg/translations.xml index 94e050727d..3f38b1991f 100644 --- a/libraries/ui-strings/src/main/res/values-bg/translations.xml +++ b/libraries/ui-strings/src/main/res/values-bg/translations.xml @@ -145,7 +145,6 @@ "Създаване на стая…" "Стаята е напусната" "Пространството е напуснато" - "Тъмен" "Грешка при разшифроване" "Описание" "Опции за разработчици" @@ -176,7 +175,6 @@ "Този Matrix ID не може да бъде намерен, така че поканата може да не бъде получена." "Стаята се напуска" "Пространството се напуска" - "Светъл" "Връзката е копирана в клипборда" "Зарежда се…" "Зарежда се още…" @@ -231,7 +229,6 @@ "%1$d отговора" "В отговор на %1$s" - "Съобщаване за грешка" "Съобщаване за проблем" "Докладът е изпратен" "Редактор на богат текст" @@ -270,7 +267,6 @@ "Успешно" "Предложения" "Синхронизиране" - "Система" "Текст" "Уведомления от трети страни" "Нишка" diff --git a/libraries/ui-strings/src/main/res/values-cs/translations.xml b/libraries/ui-strings/src/main/res/values-cs/translations.xml index 4343f2980b..36bd188c2a 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -198,7 +198,6 @@ "Pokročilá nastavení" "obrázek" "Analytika" - "Synchronizace oznámení…" "Opustili jste místnost" "Byli jste odhlášeni z relace" "Vzhled" @@ -216,7 +215,6 @@ "Místnost opuštěna" "Opustit prostor" "Pozvánka odmítnuta" - "Tmavé" "Chyba dešifrování" "Popis" "Možnosti pro vývojáře" @@ -242,6 +240,7 @@ Důvod: %1$s." "Selhalo" "Oblíbené" "Oblíbené" + "Synchronizace oznámení…" "Soubor" "Soubor smazán" "Soubor uložen" @@ -255,7 +254,6 @@ Důvod: %1$s."
"Tento Matrix identifikátor nelze najít, takže pozvánka nemusí být přijata." "Opuštění místnosti" "Opuštění prostoru" - "Světlý" "Řádek zkopírován do schránky" "Odkaz zkopírován do schránky" "Připojit nové zařízení" @@ -324,7 +322,6 @@ Důvod: %1$s." "%1$d odpovědí" "Odpověď na %1$s" - "Nahlásit chybu" "Nahlásit problém" "Zpráva odeslána" "Editor formátovaného textu" @@ -381,7 +378,6 @@ Důvod: %1$s." "Doporučeno" "Návrhy" "Synchronizace" - "Systém" "Text" "Oznámení třetích stran" "Vlákno" diff --git a/libraries/ui-strings/src/main/res/values-cy/translations.xml b/libraries/ui-strings/src/main/res/values-cy/translations.xml index 9c4b04b9d5..00e2a39297 100644 --- a/libraries/ui-strings/src/main/res/values-cy/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cy/translations.xml @@ -198,7 +198,6 @@ "Wedi gadael yr ystafell" "Gofod chwith" "Wedi gwrthod y gwahoddiad" - "Tywyll" "Gwall dadgryptio" "Disgrifiad" "Dewisiadau datblygwr" @@ -235,7 +234,6 @@ Rheswm: %1$s." "Gosod APK" "Nid oes modd dod o hyd i\'r ID Matrics hwn, felly mae\'n bosibl na fydd y gwahoddiad yn cael ei dderbyn." "Gadael ystafell" - "Golau" "Llinell wedi\'i chopïo i\'r clipfwrdd" "Dolen wedi\'i chopïo i\'r clipfwrdd" "Yn Llwytho…" @@ -309,7 +307,6 @@ Rheswm: %1$s." "%1$d ateb" "Yn ymateb i %1$s" - "Adrodd ar wall" "Adrodd am broblem" "Adroddiad wedi ei gyflwyno" "Golygydd testun cyfoethog" @@ -360,7 +357,6 @@ Rheswm: %1$s." "Llwyddiant" "Awgrymiadau" "Cydweddu" - "System" "Testun" "Hysbysiadau trydydd parti" "Edefyn" diff --git a/libraries/ui-strings/src/main/res/values-da/translations.xml b/libraries/ui-strings/src/main/res/values-da/translations.xml index f1ff7ec747..ce79b8972b 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -198,7 +198,6 @@ "Avancerede indstillinger" "et billede" "Analyse-værktøj" - "Synkroniserer notifikationer…" "Du forlod rummet" "Du blev logget ud af sessionen" "Udseende" @@ -218,7 +217,6 @@ "Forlod rummet" "Forlod klynge" "Invitationen blev afvist" - "Mørkt tema" "Fejl under dekryptering" "Beskrivelse" "Indstillinger for udviklere" @@ -244,6 +242,7 @@ "Mislykkedes" "Favorit" "Favoritmarkeret" + "Synkroniserer notifikationer…" "Fil" "Fil slettet" "Fil gemt" @@ -257,7 +256,6 @@ "Dette Matrix-ID kan ikke findes, så invitationen modtages muligvis ikke." "Forlader rummet" "Forlader klynge" - "Lyst tema" "Linje kopieret til udklipsholder" "Linket er kopieret til udklipsholderen" "Forbind ny enhed" @@ -323,7 +321,6 @@ "%1$d svar" "Svarer til %1$s" - "Rapportér en fejl" "Anmeld et problem" "Anmeldelsen er indsendt" "Rich text editor" @@ -377,7 +374,6 @@ "Forslag" "Forslag" "Synkroniserer" - "System" "Tekst" "Tredjepartsmeddelelser" "Tråd" diff --git a/libraries/ui-strings/src/main/res/values-de/translations.xml b/libraries/ui-strings/src/main/res/values-de/translations.xml index 739d003f88..5b7f52cf4e 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -192,7 +192,6 @@ "Erweiterte Einstellungen" "ein Bild" "Analysedaten" - "Benachrichtigungen werden synchronisiert…" "Du hast den Chat verlassen" "Du wurdest aus der Sitzung abgemeldet." "Erscheinungsbild" @@ -210,7 +209,6 @@ "Hat den Chat verlassen" "Space verlassen" "Einladung abgelehnt" - "Dunkel" "Dekodierungsfehler" "Beschreibung" "Entwickleroptionen" @@ -236,6 +234,7 @@ Grund: %1$s." "Fehlgeschlagen" "Favorit" "Favorisiert" + "Benachrichtigungen werden synchronisiert…" "Datei" "Datei wurde gelöscht" "Datei gespeichert" @@ -249,7 +248,6 @@ Grund: %1$s." "Diese Matrix Kennung wurde nicht gefunden, daher wird die Einladung möglicherweise nicht empfangen." "Chat verlassen" "Space wird verlassen" - "Hell" "Zeile in die Zwischenablage kopiert" "Link in die Zwischenablage kopiert" "Neues Gerät verknüpfen" @@ -316,7 +314,6 @@ Grund: %1$s." "%1$d Antworten" "%1$s antworten" - "Einen Fehler melden" "Ein Problem melden" "Bericht eingereicht" "Rich-Text-Editor" @@ -370,7 +367,6 @@ Grund: %1$s." "Empfohlen" "Vorschläge" "Synchronisieren" - "System" "Text" "Hinweise von Drittanbietern" "Thread" diff --git a/libraries/ui-strings/src/main/res/values-el/translations.xml b/libraries/ui-strings/src/main/res/values-el/translations.xml index beb97c54d1..ec14b73e04 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -120,6 +120,7 @@ "Αποχώρηση από τον χώρο" "Φόρτωσε περισσότερα" "Διαχείριση λογαριασμού" + "Διαχείριση λογαριασμού και συσκευών" "Διαχείριση συσκευών" "Διαχείριση αίθουσών" "Στείλε" @@ -170,6 +171,7 @@ "Ξανά από την αρχή" "Έναρξη επαλήθευσης" "Πάτα για φόρτωση χάρτη" + "Διακοπή" "Τράβηξε φωτογραφία" "Πάτα για επιλογές" "Μετάφραση" @@ -190,7 +192,6 @@ "Ρυθμίσεις για προχωρημένους" "μια εικόνα" "Στατιστικά στοιχεία" - "Συγχρονισμός ειδοποιήσεων…" "Αποχωρήσατε από την αίθουσα" "Αποσυνδεθήκατε από την περίοδο λειτουργίας" "Εμφάνιση" @@ -208,7 +209,6 @@ "Αποχώρησε από την αίθουσα" "Αποχωρήσατε από τον χώρο" "Η πρόσκληση απορρίφθηκε" - "Σκοτεινό" "Σφάλμα αποκρυπτογράφησης" "Περιγραφή" "Επιλογές προγραμματιστή" @@ -224,6 +224,7 @@ "Κενό αρχείο" "Κρυπτογράφηση" "Η κρυπτογράφηση ενεργοποιήθηκε" + "Τελειώνει στις %1$s" "Εισήγαγε το PIN σου" "Σφάλμα" "Παρουσιάστηκε σφάλμα, ενδέχεται να μην λαμβάνεις ειδοποιήσεις για νέα μηνύματα. Αντιμετώπισε το πρόβλημα με τις ειδοποιήσεις από τις ρυθμίσεις. @@ -233,6 +234,7 @@ "Απέτυχε" "Αγαπημένο" "Είναι αγαπημένο" + "Συγχρονισμός ειδοποιήσεων…" "Αρχείο" "Το αρχείο διαγράφηκε" "Το αρχείο αποθηκεύτηκε" @@ -246,10 +248,11 @@ "Αυτό το Matrix ID δεν μπορεί να βρεθεί, επομένως η πρόσκληση ενδέχεται να μην ληφθεί." "Αποχώρηση από την αίθουσα" "Αποχωρείτε από τον χώρο" - "Φωτεινό" "Η γραμμή αντιγράφηκε στο πρόχειρο" "Ο σύνδεσμος αντιγράφηκε στο πρόχειρο" "Σύνδεση νέας συσκευής" + "Ζωντανή τοποθεσία" + "Η ζωντανή τοποθεσία έληξε" "Φόρτωση…" "Φόρτωση περισσότερων…" @@ -311,7 +314,6 @@ "%1$d απαντήσεις" "Απάντηση σε %1$s" - "Αναφορά σφάλματος" "Αναφορά προβλήματος" "Η αναφορά υποβλήθηκε" "Επεξεργαστής εμπλουτισμένου κειμένου" @@ -346,6 +348,7 @@ "Ρυθμίσεις" "Κοινή χρήση χώρου" "Τα νέα μέλη βλέπουν το ιστορικό" + "Κοινόχρηστη ζωντανή τοποθεσία" "Κοινόχρηστη τοποθεσία" "Κοινόχρηστος χώρος" "Αφαίρεση συσκευής" @@ -364,10 +367,10 @@ "Προτεινόμενο" "Προτάσεις" "Συγχρονισμός" - "Σύστημα" "Κείμενο" "Ειδοποιήσεις τρίτων" "Νήμα" + "Νήματα" "Θέμα" "Τι αφορά αυτή η αίθουσα;" "Δεν είναι δυνατή η αποκρυπτογράφηση" @@ -398,6 +401,7 @@ "Φωνητικό μήνυμα" "Αναμονή…" "Αναμονή για αυτό το μήνυμα" + "Αναμονή για ζωντανή τοποθεσία…" "Οποιοσδήποτε μπορεί να δει το ιστορικό" "Εσύ" "%1$s (%2$s) μοιράστηκε αυτό το μήνυμα, καθώς δεν ήσασταν στην αίθουσα όταν στάλθηκε." diff --git a/libraries/ui-strings/src/main/res/values-es/translations.xml b/libraries/ui-strings/src/main/res/values-es/translations.xml index fa0bc700cb..b03223a70e 100644 --- a/libraries/ui-strings/src/main/res/values-es/translations.xml +++ b/libraries/ui-strings/src/main/res/values-es/translations.xml @@ -165,7 +165,6 @@ "Solicitud cancelada" "Saliste de la sala" "Invitación rechazada" - "Oscuro" "Error de descifrado" "Opciones de desarrollador" "ID de dispositivo" @@ -201,7 +200,6 @@ Motivo: %1$s." "Instalar APK" "No se encontró este ID de Matrix, por lo que es posible que no se reciba la invitación." "Saliendo de la sala" - "Claro" "Línea copiada al portapapeles" "Enlace copiado al portapapeles" "Cargando…" @@ -251,7 +249,6 @@ Motivo: %1$s." "Clave de recuperación" "Recargando…" "Respondiendo a %1$s" - "Informar de un error" "Informar de un problema" "Informe enviado" "Editor de texto enriquecido" @@ -281,7 +278,6 @@ Motivo: %1$s." "Terminado" "Sugerencias" "Sincronizando" - "Sistema" "Texto" "Avisos de terceros" "Hilo" diff --git a/libraries/ui-strings/src/main/res/values-et/translations.xml b/libraries/ui-strings/src/main/res/values-et/translations.xml index beedf175bd..1669abc4e0 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -69,6 +69,7 @@ "Helista" "Loobu" "Hetkel jäta tegemata" + "Vali fail" "Vali foto" "Selge" "Sulge" @@ -88,12 +89,15 @@ "Eemalda konto kasutusest" "Keeldu" "Keeldu ja blokeeri" + "Kustuta" + "Kustuta kasutajakonto" "Kustuta küsitlus" "Eemalda kõik valikud" "Lülita välja" "Loobu" "Lõpeta" "Valmis" + "Laadi alla" "Muuda" "Muuda selgitust" "Muuda küsitlust" @@ -193,7 +197,6 @@ "Täiendavad seadistused" "pilt" "Analüütika" - "Sünkroonin teavitusi…" "Sina lahkusid jututoast" "Sa olid sessioonist väljaloginud" "Välimus" @@ -201,7 +204,9 @@ "Beetaversioon" "Blokeeritud kasutajad" "Mullid" + "Osapool keeldus kõnest" "Kõne algas" + "Sa keeldusid kõnest" "Vestluse varukoopia" "Kopeeritud lõikelauale" "Autoriõigused" @@ -211,7 +216,6 @@ "Lahkus jututoast" "Lahkus kogukonnast" "Keeldusid kutsest" - "Tume" "Dekrüptimisviga" "Kirjeldus" "Arendaja valikud" @@ -236,6 +240,7 @@ Põhjus: %1$s." "Ei õnnestunud" "Lemmik" "Märgitud lemmikuks" + "Sünkroonin teavitusi…" "Fail" "Fail on kustutatud" "Fail on salvestatud" @@ -249,10 +254,11 @@ Põhjus: %1$s." "Sellist Matrix\'i kasutajatunnust ei õnnestu leida, seega sõnumit ilmselt keegi kätte ei saa." "Oled lahkumas jututoast" "Oled lahkumas kogukonnast" - "Hele" "Rida on kopeeritud lõikelauale" "Link on kopeeritud lõikelauale" "Seo uus seade" + "Asukoha jagamine reaalajas" + "Reaalajas asukoha jagamine on lõppenud" "Laadime…" "Laadime veel…" @@ -279,6 +285,7 @@ Põhjus: %1$s." "Võrgust väljas" "Avatud lähtekoodiga litsentsid" "või" + "Muud valikud" "Salasõna" "Inimesed" "Püsilink" @@ -313,7 +320,6 @@ Põhjus: %1$s." "%1$d vastust" "Vastates kasutajale %1$s" - "Teata veast" "Teata veast" "Veateade on saadetud" "Vormindatud teksti toimeti" @@ -366,7 +372,6 @@ Põhjus: %1$s." "Soovitatud" "Soovitused" "Sünkroniseerime" - "Süsteem" "Tekst" "Kolmandate osapoolte teatised" "Jutulõng" @@ -401,6 +406,7 @@ Põhjus: %1$s." "Häälsõnum" "Ootame…" "Ootame selle sõnumi dekrüptimisvõtit" + "Ootan asukoha jagamist reaalajas…" "Kõik võivad ajalugu näha" "Sina" "Kuna sind polnud saatmise ajal jututoas, siis %1$s (%2$s) jagas seda sõnumit sinuga." @@ -461,6 +467,11 @@ Kas sa oled kindel, et soovid jätkata?" "Seadistused" "Mitte keegi ei jaga oma asukohta" "Asukoht on jagamisel reaalajas" + + "%1$d isik" + "%1$d isikut" + + "Kaardil" "Meediafaili valimine ei õnnestunud. Palun proovi uuesti." "Siia lisamiseks vajuta sõnumil ja vali „%1$s“." "Et olulisi sõnumeid oleks lihtsam leida, tõsta nad esile" @@ -485,6 +496,7 @@ Kas sa oled kindel, et soovid jätkata?" "Sõnum jututoas %1$s" "Näita rohkem" "Näita vähem" + "Asukoht on jagamisel reaalajas" "Sa juba vaatad seda jututuba!" "%1$s / %2$s" "%1$s esiletõstetud sõnumit" diff --git a/libraries/ui-strings/src/main/res/values-eu/translations.xml b/libraries/ui-strings/src/main/res/values-eu/translations.xml index bef5f1a4b5..0c046b8bb4 100644 --- a/libraries/ui-strings/src/main/res/values-eu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-eu/translations.xml @@ -169,7 +169,6 @@ "Eskaera bertan behera utzi da" "Gelatik atera da" "Gonbidapenari uko egin zaio" - "Iluna" "Deszifratze-errorea" "Garapen aukerak" "Gailuaren IDa" @@ -204,7 +203,6 @@ Arrazoia: %1$s." "Instalatu APK" "Matrix IDa ezin da topatu eta, beraz, litekeena da gonbidapena ez jasotzea." "Gelatik ateratzen" - "Argia" "Lerroa arbelean kopiatu da" "Esteka arbelean kopiatu da" "Kargatzen…" @@ -256,7 +254,6 @@ Arrazoia: %1$s." "Berreskuratze-gakoa" "Freskatzen…" "%1$s(r)i erantzuten" - "Eman akats baten berri" "Eman arazo baten berri" "Salaketa bidali da" "Testu aberatsaren editorea" @@ -288,7 +285,6 @@ Arrazoia: %1$s." "Arrakasta" "Iradokizunak" "Sinkronizatzen" - "Sistema" "Testua" "Hirugarrenei buruzko oharrak" "Haria" diff --git a/libraries/ui-strings/src/main/res/values-fa/translations.xml b/libraries/ui-strings/src/main/res/values-fa/translations.xml index 872493f7de..c14f281f0d 100644 --- a/libraries/ui-strings/src/main/res/values-fa/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fa/translations.xml @@ -146,7 +146,7 @@ "نمایش" "ورود دوباره" "برداشتن این افزاره" - "خروج به هر صورت" + "به هر حال این دستگاه را حذف کنید" "پرش" "آغاز" "آغاز گپ" @@ -185,7 +185,6 @@ "اتاق را ترک کرد" "فضا را ترک کرد" "دعوت لغو شد" - "تیره" "خطای رمزگشایی" "توضیح" "گزینه‌های توسعه دهنده" @@ -220,11 +219,14 @@ "شناسهٔ ماتریکس نتوانست پیدا شود. ممکن است دعوت نرسیده باشد." "ترک کردن اتاق" "ترک کردن فضا" - "روشن" "خط در تخته‌گیره رونوشت شد" "پیوند در تخته‌گیره رونوشت شد" "بار کردن…" "بار کردن بیش‌تر…" + + "%d دیگر" + "%d دیگران" + "%1$d عضو" "%1$d عضو" @@ -270,7 +272,6 @@ "کلید بازیابی" "تازه سازی…" "پاسخ دادن به %1$s" - "گزارش یک اشکال" "گزارش مشکل" "گزارش ثبت شد" "ویرایشگر متن غنی" @@ -305,7 +306,6 @@ "موفّقیت" "پیشنهادها" "هم‌گام ساختن" - "سامانه" "متن" "تذکّرهای سوم‌شخص" "رشته" diff --git a/libraries/ui-strings/src/main/res/values-fi/translations.xml b/libraries/ui-strings/src/main/res/values-fi/translations.xml index 48601352ba..d5093590ca 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -193,7 +193,6 @@ "Edistyneet asetukset" "kuva" "Analytiikka" - "Synkronoidaan ilmoituksia…" "Poistuit huoneesta" "Sinut kirjattiin ulos istunnosta" "Ulkoasu" @@ -211,7 +210,6 @@ "Poistuit huoneesta" "Poistuit tilasta" "Kutsu hylätty" - "Tumma" "Salauksen purkuvirhe" "Kuvaus" "Kehittäjän asetukset" @@ -237,6 +235,7 @@ Syy: %1$s." "Epäonnistui" "Lisää suosikkeihin" "Lisätty suosikkeihin" + "Synkronoidaan ilmoituksia…" "Tiedosto" "Tiedosto poistettu" "Tiedosto tallennettu" @@ -250,7 +249,6 @@ Syy: %1$s." "Tätä Matrix-tunnusta ei löytynyt, joten kutsu ei välttämättä mene perille." "Poistutaan huoneesta" "Poistutaan tilasta" - "Vaalea" "Rivi kopioitu leikepöydälle" "Linkki kopioitu leikepöydälle" "Yhdistä uusi laite" @@ -317,7 +315,6 @@ Syy: %1$s." "%1$d vastausta" "Vastataan käyttäjälle %1$s" - "Ilmoita virheestä" "Ilmoita ongelmasta" "Ilmoitus lähetetty" "Rikastettu tekstieditori" @@ -371,7 +368,6 @@ Syy: %1$s." "Ehdotettu" "Ehdotukset" "Synkronoidaan" - "Järjestelmän oletus" "Teksti" "Kolmannen osapuolen ilmoitukset" "Viestiketju" diff --git a/libraries/ui-strings/src/main/res/values-fr/translations.xml b/libraries/ui-strings/src/main/res/values-fr/translations.xml index 7e0c4e9481..545cf66c73 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -198,7 +198,6 @@ "Paramètres avancés" "une image" "Statistiques d’utilisation" - "Synchronisation des notifications…" "Vous avez quitté le salon" "Vous avez été déconnecté de la session" "Apparence" @@ -218,7 +217,6 @@ "Vous avez quitté le salon" "Vous avez quitté l’espace" "Invitation refusée" - "Sombre" "Erreur de déchiffrement" "Description" "Options pour les développeurs" @@ -244,6 +242,7 @@ Raison : %1$s." "Échec" "Favori" "Ajouté aux favoris" + "Synchronisation des notifications…" "Fichier" "Fichier supprimé" "Fichier enregistré" @@ -257,7 +256,6 @@ Raison : %1$s." "Cet identifiant Matrix est introuvable, il est donc possible que l’invitation ne soit pas reçue." "Quitter le salon…" "En train de quitter l’espace" - "Clair" "Ligne copiée dans le presse-papiers" "Lien copié dans le presse-papiers" "Associer un nouvel appareil" @@ -324,7 +322,6 @@ Raison : %1$s." "%1$d réponses" "En réponse à %1$s" - "Signaler un problème" "Remonter un problème" "Rapport soumis" "Éditeur de texte enrichi" @@ -378,7 +375,6 @@ Raison : %1$s." "Recommandé" "Suggestions" "Synchronisation" - "Système" "Texte" "Avis de tiers" "Fil de discussion" diff --git a/libraries/ui-strings/src/main/res/values-hr/translations.xml b/libraries/ui-strings/src/main/res/values-hr/translations.xml index 2382eafc1a..369d8ccce4 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -200,7 +200,6 @@ "Napredne postavke" "slika" "Analitika" - "Sinkronizacija obavijesti…" "Napustili ste sobu" "Odjavljeni ste iz sesije" "Izgled" @@ -220,7 +219,6 @@ "Napustio/la je sobu" "Napušteni prostor" "Poziv je odbijen" - "Tamno" "Pogreška kod dešifriranja" "Opis" "Mogućnosti za razvojne inženjere" @@ -246,6 +244,7 @@ Razlog: %1$s ." "Nije uspjelo" "Favorit" "Označeno kao favorit" + "Sinkronizacija obavijesti…" "Datoteka" "Datoteka je izbrisana" "Datoteka je spremljena" @@ -259,7 +258,6 @@ Razlog: %1$s ." "Ovaj Matrix ID nije moguće pronaći, pa se pozivnica možda neće primiti." "Izlazak iz sobe" "Napuštanje prostora" - "Svijetlo" "Redak je kopiran u međuspremnik" "Poveznica je kopirana u međuspremnik." "Poveži novi uređaj" @@ -330,7 +328,6 @@ Razlog: %1$s ." "%1$d odgovora" "Odgovara korisniku %1$s" - "Prijavi pogrešku" "Prijavi problem" "Prijava je podnesena" "Uređivač obogaćenog teksta" @@ -386,7 +383,6 @@ Razlog: %1$s ." "Preporučeno" "Prijedlozi" "Sinkronizacija" - "Sustav" "Tekst" "Obavijesti trećih strana" "Nit" diff --git a/libraries/ui-strings/src/main/res/values-hu/translations.xml b/libraries/ui-strings/src/main/res/values-hu/translations.xml index f6498f228f..7acfb90ef7 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -71,6 +71,7 @@ "Hívás" "Mégse" "Egyelőre nem" + "Fájl kiválasztása" "Fénykép kiválasztása" "Törlés" "Bezárás" @@ -198,7 +199,6 @@ "Speciális beállítások" "egy kép" "Elemzések" - "Értesítések szinkronizálása…" "Elhagyta a szobát" "Ki lett jelentkeztetve a munkamenetből" "Megjelenítés" @@ -218,7 +218,6 @@ "Elhagyta a szobát" "Tér elhagyva" "Meghívás elutasítva" - "Sötét" "Visszafejtési hiba" "Leírás" "Fejlesztői beállítások" @@ -244,6 +243,7 @@ Ok: %1$s." "Sikertelen" "Kedvenc" "Kedvencnek jelölve" + "Értesítések szinkronizálása…" "Fájl" "Fájl törölve" "A fájl mentve" @@ -257,7 +257,6 @@ Ok: %1$s." "Ez a Matrix-azonosító nem található, ezért előfordulhat, hogy a meghívó nem érkezik meg." "Szoba elhagyása" "Tér elhagyása" - "Világos" "A sor a vágólapra másolva" "Hivatkozás a vágólapra másolva" "Új eszköz összekapcsolása" @@ -323,7 +322,6 @@ Ok: %1$s." "%1$d válasz" "Válasz %1$s számára" - "Hiba jelentése" "Probléma jelentése" "A jelentés elküldve" "Formázott szöveges szerkesztő" @@ -377,7 +375,6 @@ Ok: %1$s." "Javaslat" "Javaslatok" "Szinkronizálás" - "Rendszer" "Szöveg" "Harmadik felek nyilatkozatai" "Üzenetszál" @@ -466,6 +463,9 @@ Biztos, hogy folytatja?" "Elnézést, hiba történt" "🔐️ Csatlakozz hozzám itt: %1$s" "Beszélgessünk itt: %1$s, %2$s" + "Élő földrajzi hely megosztása" + "Helymegosztás folyamatban" + "Élő hely: %1$s" "%1$s Android" "Az eszköz rázása a hibajelentéshez" "Képernyőkép" diff --git a/libraries/ui-strings/src/main/res/values-in/translations.xml b/libraries/ui-strings/src/main/res/values-in/translations.xml index 77e405e1c8..51d78530a8 100644 --- a/libraries/ui-strings/src/main/res/values-in/translations.xml +++ b/libraries/ui-strings/src/main/res/values-in/translations.xml @@ -185,7 +185,6 @@ "Permintaan dibatalkan" "Keluar dari ruangan" "Undangan ditolak" - "Gelap" "Kesalahan dekripsi" "Deskripsi" "Opsi pengembang" @@ -222,7 +221,6 @@ Alasan: %1$s." "Pasang APK" "ID Matrix ini tidak dapat ditemukan, sehingga undangan mungkin tidak diterima." "Meninggalkan ruangan" - "Terang" "Baris disalin ke papan klip" "Tautan disalin ke papan klip" "Memuat…" @@ -275,7 +273,6 @@ Alasan: %1$s." "%1$d balasan" "Membalas %1$s" - "Laporkan kutu" "Laporkan masalah" "Laporan terkirim" "Penyunting teks kaya" @@ -309,7 +306,6 @@ Alasan: %1$s." "Berhasil" "Saran" "Menyinkronkan" - "Sistem" "Teks" "Pemberitahuan pihak ketiga" "Utas" diff --git a/libraries/ui-strings/src/main/res/values-it/translations.xml b/libraries/ui-strings/src/main/res/values-it/translations.xml index 824b9f6441..d1ec78d920 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -14,6 +14,7 @@ "Dettagli sulla crittografia" "Allarga il campo di testo del messaggio" "Nascondi password" + "Info" "Entra in chiamata" "Vai alla fine" "Sposta la mappa sulla mia posizione" @@ -48,6 +49,7 @@ "Invia file" "Posizione del mittente" "Azione richiesta a tempo limitato, hai un minuto per la verifica" + "Impostazioni, azione richiesta" "Mostra password" "Avvia una chiamata" "Avvia una videochiamata" @@ -69,6 +71,7 @@ "Chiama" "Annulla" "Annulla per ora" + "Scegli il file" "Scegli foto" "Cancella" "Chiudi" @@ -88,12 +91,15 @@ "Disattiva account" "Rifiuta" "Rifiuta e blocca" + "Elimina" + "Elimina account" "Elimina sondaggio" "Deseleziona tutti" "Disabilita" "Annulla" "Chiudi" "Fine" + "Scarica" "Modifica" "Modifica didascalia" "Modifica sondaggio" @@ -193,7 +199,6 @@ "Impostazioni avanzate" "un\'immagine" "Statistiche di utilizzo" - "Sincronizzazione delle notifiche…" "Hai lasciato la stanza" "Sei stato disconnesso dalla sessione" "Aspetto" @@ -201,7 +206,9 @@ "Beta" "Utenti bloccati" "Fumetti" + "Chiamata rifiutata" "Chiamata avviata" + "Hai rifiutato una chiamata" "Backup della chat" "Copiato negli appunti" "Copyright" @@ -211,7 +218,6 @@ "Hai lasciato la stanza" "Hai lasciato lo spazio" "Invito rifiutato" - "Scuro" "Errore di decrittazione" "Descrizione" "Opzioni sviluppatore" @@ -237,6 +243,7 @@ Motivo:. %1$s" "Fallito" "Preferiti" "Preferita" + "Sincronizzazione delle notifiche…" "File" "File eliminato" "File salvato" @@ -250,7 +257,6 @@ Motivo:. %1$s" "Questo ID Matrix non può essere trovato, quindi l\'invito potrebbe non essere ricevuto." "Lascio la stanza" "Uscendo dallo spazio" - "Chiaro" "Riga copiata negli appunti" "Collegamento copiato negli appunti" "Collega un nuovo dispositivo" @@ -317,7 +323,6 @@ Motivo:. %1$s" "%1$d risposte" "Risposta a %1$s" - "Segnala un problema" "Segnala un problema" "Segnalazione inviata" "Editor di testo avanzato" @@ -371,7 +376,6 @@ Motivo:. %1$s" "Suggeriti" "Suggerimenti" "Sincronizzazione" - "Sistema" "Testo" "Comunicazioni di terze parti" "Discussione" @@ -460,6 +464,8 @@ Sei sicuro di voler continuare?" "Siamo spiacenti, si è verificato un errore" "🔐️ Unisciti a me su %1$s" "Ehi, parliamo su %1$s: %2$s" + "Condivisione della posizione in corso" + "%1$s Posizione in tempo reale" "%1$s Android" "Scuoti per segnalare un problema" "Istantanea schermo" @@ -467,6 +473,13 @@ Sei sicuro di voler continuare?" "Risposte" "Rimuovi %1$s" "Impostazioni" + "Nessuno sta condividendo la propria posizione" + "Condivisione posizione in tempo reale" + + "%1$d persona" + "%1$d persone" + + "Sulla mappa" "Selezione del file multimediale fallita, riprova." "Premi su un messaggio e scegli “%1$s” per includerlo qui." "Fissa i messaggi importanti così che possano essere trovati facilmente" @@ -491,6 +504,7 @@ Sei sicuro di voler continuare?" "Messaggio in %1$s" "Espandi" "Riduci" + "Condivisione posizione in tempo reale" "Stai già visualizzando questa stanza!" "%1$s di %2$s" "%1$s Messaggi fissati" diff --git a/libraries/ui-strings/src/main/res/values-ja/translations.xml b/libraries/ui-strings/src/main/res/values-ja/translations.xml index 1c022f850f..c62c579f32 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -197,7 +197,6 @@ "高度な設定" "画像" "分析" - "通知を同期中…" "あなたがルームを退出" "セッションからログアウトされました" "テーマ" @@ -217,7 +216,6 @@ "ルームを退出しました" "スペースから退出しました" "招待は却下されました" - "ダーク" "復号化エラー" "詳細" "開発者向けオプション" @@ -243,6 +241,7 @@ "失敗" "お気に入り" "お気に入り" + "通知を同期中…" "ファイル" "ファイルを削除しました" "ファイルを保存しました" @@ -256,7 +255,6 @@ "このMatrix IDは見つからないため、招待が届かない可能性があります。" "ルームを退出しています" "スペースを退出しています" - "ライト" "行をクリップボードにコピーしました" "リンクをクリップボードにコピーしました" "新しい端末から接続" @@ -319,7 +317,6 @@ "%1$d 件の返信" "%1$s に返信" - "バグを報告" "問題を報告" "報告は送信されました" "リッチテキストエディター" @@ -370,7 +367,6 @@ "推奨される" "提案" "同期中" - "システム" "テキスト" "第三者に関する通知" "スレッド" diff --git a/libraries/ui-strings/src/main/res/values-ka/translations.xml b/libraries/ui-strings/src/main/res/values-ka/translations.xml index b7a8819391..2be4e43d61 100644 --- a/libraries/ui-strings/src/main/res/values-ka/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ka/translations.xml @@ -122,7 +122,6 @@ "საავტორო უფლება" "ოთახის შექმნა…" "დატოვა ოთახი" - "მუქი" "გაშიფვრის შეცდომა" "დეველოპერის პარამეტრები" "პირდაპირი ჩატი" @@ -145,7 +144,6 @@ "დააინსტალირეთ APK" "ეს Matrix ID ვერ მოიძებნა, ამიტომ მოწვევა შეიძლება არ იყოს მიღებული." "ოთახის დატოვება" - "ღია" "ბმული კოპირებულია გაცვლის ბუფერში" "იტვირთება…" @@ -186,7 +184,6 @@ "განახლება…" "პასუხი %1$s-ს" - "ხარვეზის შეტყობინება" "შეტყობინება პრობლემაზე" "რეპორტი გაგზავნილია" "მდიდარი ტექსტის რედაქტორი" @@ -213,7 +210,6 @@ "წარმატება" "შეთავაზებები" "სინქრონიზაცია" - "სისტემა" "ტექსტი" "მესამე პირის შენიშვნები" "თემა" diff --git a/libraries/ui-strings/src/main/res/values-ko/translations.xml b/libraries/ui-strings/src/main/res/values-ko/translations.xml index 6a87870658..303e8ba929 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -190,7 +190,6 @@ "고급 설정" "이미지" "통계" - "알림 동기화 중…" "방을 떠남" "세션에서 로그아웃되었습니다." "외관" @@ -208,7 +207,6 @@ "방 떠남" "스페이스 떠남" "초대 거부됨" - "다크" "복호화 오류" "설명" "개발자 설정" @@ -234,6 +232,7 @@ "실패" "즐겨찾기" "즐겨찾기 됨" + "알림 동기화 중…" "파일" "파일 삭제됨" "파일 저장됨" @@ -247,7 +246,6 @@ "Matrix ID를 찾을 수 없기 때문에 초대가 수신되지 않을 수도 있습니다." "방을 떠나는 중" "스페이스 떠나는 중" - "라이트" "줄이 클립보드에 복사되었습니다." "링크가 클립보드에 복사됨" "새 기기 연결" @@ -310,7 +308,6 @@ "%1$d 답변" "%1$s님에게 답장하는 중" - "버그 보고" "문제 보고" "보고 제출됨" "리치 텍스트 편집기" @@ -361,7 +358,6 @@ "공유된 스페이스" "제안" "동기화 중" - "시스템" "글자" "제3자 고지" "스레드" diff --git a/libraries/ui-strings/src/main/res/values-lt/translations.xml b/libraries/ui-strings/src/main/res/values-lt/translations.xml index 280209f6a5..da5281212e 100644 --- a/libraries/ui-strings/src/main/res/values-lt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-lt/translations.xml @@ -126,7 +126,6 @@ "Reakcijos" "Atnaujinama…" "Atsakant %1$s" - "Pranešti apie klaidą" "Skundas pateiktas" "Kambario pavadinimas" "pvz., jūsų projekto pavadinimas" diff --git a/libraries/ui-strings/src/main/res/values-nb/translations.xml b/libraries/ui-strings/src/main/res/values-nb/translations.xml index fc641df34d..aa594f8027 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -207,7 +207,6 @@ "Forlot rommet" "Forlot område" "Invitasjon avslått" - "Mørk" "Dekrypteringsfeil" "Beskrivelse" "Alternativer for utviklere" @@ -245,7 +244,6 @@ "Finner ikke denne Matrix-IDen, så invitasjonen blir kanskje ikke mottatt." "Forlater rommet" "Forlater området" - "Lys" "Linje kopiert til utklippstavlen" "Lenke kopiert til utklippstavlen" "Koble til ny enhet" @@ -309,7 +307,6 @@ "%1$d svar" "Svar til %1$s" - "Rapporter en feil" "Rapporter et problem" "Rapport sendt inn" "Redigeringsprogram for rik tekst" @@ -361,7 +358,6 @@ "Foreslått" "Forslag" "Synkroniserer" - "System" "Tekst" "Varsler fra tredjeparter" "Tråd" diff --git a/libraries/ui-strings/src/main/res/values-nl/translations.xml b/libraries/ui-strings/src/main/res/values-nl/translations.xml index 6e136e7d77..3edeeb00a0 100644 --- a/libraries/ui-strings/src/main/res/values-nl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nl/translations.xml @@ -172,7 +172,6 @@ "Kamer maken…" "Heeft de kamer verlaten" "Uitnodiging geweigerd" - "Donker" "Decryptie fout" "Ontwikkelaarsopties" "Apparaat-ID" @@ -200,7 +199,6 @@ Reden: %1$s." "APK installeren" "Deze Matrix-ID kan niet worden gevonden, dus de uitnodiging is mogelijk niet ontvangen." "De kamer verlaten" - "Licht" "Link gekopieerd naar klembord" "Laden…" @@ -250,7 +248,6 @@ Reden: %1$s." "%1$d antwoorden" "Reageren op %1$s" - "Een fout melden" "Meld een probleem" "Melding ingediend" "Uitgebreide tekstverwerker" @@ -279,7 +276,6 @@ Reden: %1$s." "Geslaagd" "Suggesties" "Synchroniseren" - "Systeem" "Tekst" "Kennisgevingen van derden" "Gesprek" diff --git a/libraries/ui-strings/src/main/res/values-pl/translations.xml b/libraries/ui-strings/src/main/res/values-pl/translations.xml index 6812885c9c..fb6b06daf7 100644 --- a/libraries/ui-strings/src/main/res/values-pl/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pl/translations.xml @@ -15,6 +15,7 @@ "Szczegóły szyfrowania" "Powiększ pole tekstowe wiadomości" "Ukryj hasło" + "Informacje" "Dołącz do połączenia" "Przejdź na dół" "Przesuń mapę do mojej lokalizacji" @@ -30,8 +31,10 @@ "Pole PIN" "Przypięta lokalizacja" "Odtwórz" + "Prędkość odtwarzania" "Ankieta" "Zakończona ankieta" + "Kod QR" "Zareaguj z %1$s" "Zareaguj innym emoji" "Odczytane przez %1$s i %2$s" @@ -46,9 +49,13 @@ "Usuń reakcję z %1$s" "Awatar pokoju" "Wyślij pliki" + "Lokalizacja nadawcy" "Wymagane jest działanie ograniczone czasowo, została jedna minuta" + "Ustawienia, wymagane działanie" "Pokaż hasło" "Rozpocznij rozmowę" + "Rozpocznij rozmowę wideo" + "Rozpocznij połączenie głosowe" "Pokój nagrobkowy" "Awatar użytkownika" "Menu użytkownika" @@ -60,11 +67,13 @@ "Twój awatar" "Akceptuj" "Dodaj opis" + "Dodaj istniejące pokoje" "Dodaj do osi czasu" "Wróć" "Zadzwoń" "Anuluj" "Anuluj na razie" + "Wybierz plik" "Wybierz zdjęcie" "Wyczyść" "Zamknij" @@ -79,26 +88,32 @@ "Kopiuj tekst" "Utwórz" "Utwórz pokój" + "Utwórz przestrzeń" "Dezaktywuj" "Dezaktywuj konto" "Odrzuć" "Odrzuć i zablokuj" + "Usuń" + "Usuń konto" "Usuń ankietę" "Odznacz wszystko" "Wyłącz" "Odrzuć" "Zamknij" "Gotowe" + "Pobierz" "Edytuj" "Edytuj opis" "Edytuj ankietę" "Włącz" "Zakończ ankietę" "Wprowadź PIN" + "Przeglądaj przestrzenie publiczne" "Zakończ" "Nie pamiętasz hasła?" "Przekaż dalej" "Wróć" + "Przejdź do ról i uprawnień" "Przejdź do ustawień" "Ignoruj" "Zaproś" @@ -114,7 +129,9 @@ "Opuść przestrzeń" "Załaduj więcej" "Zarządzaj kontem" + "Zarządzaj kontem i urządzeniami" "Zarządzaj urządzeniami" + "Zarządzaj pokojami" "Wiadomość" "Minimalizuj" "Dalej" @@ -139,7 +156,7 @@ "Zgłoś treść" "Zgłoś rozmowę" "Zgłoś pokój" - "Resetuj" + "Zresetuj" "Zresetuj tożsamość" "Spróbuj ponownie" "Ponów próbę odszyfrowania" @@ -152,18 +169,21 @@ "Wyślij wiadomość głosową" "Wyślij" "Wyślij link" + "Udostępnij lokalizację na żywo" "Pokaż" "Zaloguj się ponownie" - "Wyloguj" - "Wyloguj mimo to" + "Usuń to urządzenie" + "Usuń urządzenie mimo to" "Pomiń" "Rozpocznij" "Rozpocznij chat" "Zacznij od nowa" "Rozpocznij weryfikację" "Stuknij, aby załadować mapę" + "Zatrzymaj" "Zrób zdjęcie" "Stuknij, by wyświetlić opcje" + "Przetłumacz" "Spróbuj ponownie" "Odepnij" "Wyświetl" @@ -188,16 +208,18 @@ "Beta" "Zablokowani użytkownicy" "Bąbelki" + "Połączenie odrzucone" "Rozpoczęto rozmowę" + "Odrzuciłeś połączenie" "Backup czatu" "Skopiowano do schowka" "Prawa autorskie" "Tworzenie pokoju…" + "Tworzenie przestrzeni…" "Anulowano żądanie" "Opuszczono pokój" "Opuścił przestrzeń" "Odrzucono zaproszenie" - "Ciemny" "Błąd deszyfrowania" "Opis" "Opcje programisty" @@ -213,6 +235,7 @@ "Pusty plik" "Szyfrowanie" "Szyfrowanie włączone" + "Kończy się o %1$s" "Wprowadź kod PIN" "Błąd" "Wystąpił błąd, możesz nie otrzymać powiadomień nowych wiadomości. Spróbuj naprawić powiadomienia w ustawieniach. @@ -222,6 +245,7 @@ Powód: %1$s." "Niepowodzenie" "Ulubione" "Ulubione" + "Synchronizuję powiadomienia…" "Plik" "Plik usunięty" "Plik zapisany" @@ -235,9 +259,11 @@ Powód: %1$s." "Nie można znaleźć identyfikatora Matrix ID, zaproszenie mogło nie dotrzeć." "Opuszczanie pokoju" "Opuszczam przestrzeń" - "Jasny" "Wiersz skopiowany do schowka" "Link został skopiowany do schowka" + "Powiąż nowe urządzenie" + "Lokalizacja na żywo" + "Zakończono udostępnianie lokalizacji na żywo" "Ładowanie…" "Ładuję więcej…" @@ -252,10 +278,12 @@ Powód: %1$s." "Wiadomość" "Akcje wiadomości" + "Nie udało się wysłać wiadomości" "Układ wiadomości" "Wiadomość usunięta" "Nowoczesny" "Wycisz" + "Nazwa" "%1$s (%2$s)" "Brak wyników" "Brak nazwy pokoju" @@ -264,6 +292,7 @@ Powód: %1$s." "Offline" "Licencje open-source" "lub" + "Inne opcje" "Hasło" "Osoby" "Link bezpośredni" @@ -282,8 +311,10 @@ Powód: %1$s." "Przygotowuję…" "Polityka prywatności" + "Prywatny" "Pokój prywatny" "Prywatna przestrzeń" + "Publiczny" "Pokój publiczny" "Przestrzeń publiczna" "Reakcja" @@ -291,19 +322,20 @@ Powód: %1$s." "Powód" "Klucz przywracania" "Odświeżanie…" + "Usuwanie…" "%1$d odpowiedź" "%1$d odpowiedzi" "%1$d odpowiedzi" "Odpowiadanie do %1$s" - "Zgłoś błąd" "Zgłoś problem" "Zgłoszenie wysłane" "Bogaty edytor tekstu" + "Rola" "Pokój" "Nazwa pokoju" - "np. nazwa projektu" + "np. nazwa twojego projektu" "%1$d Pokój" "%1$d Pokoje" @@ -317,6 +349,11 @@ Powód: %1$s." "Bezpieczeństwo" "Wyświetlone przez" "Wybierz konto" + + "%1$d zaznaczony" + "%1$d zaznaczone" + "%1$d zaznaczonych" + "Wyślij do" "Wysyłanie…" "Błąd wysyłania" @@ -327,12 +364,16 @@ Powód: %1$s." "Adres URL serwera" "Ustawienia" "Udostępnij przestrzeń" + "Nowi członkowie widzą historię" + "Udostępniona lokalizacja na żywo" "Udostępniona lokalizacja" "Udostępniona przestrzeń" - "Wylogowywanie" + "Usuwanie urządzenia" "Coś poszło nie tak" "Napotkaliśmy problem. Spróbuj ponownie." "Przestrzeń" + "Członkowie przestrzeni" + "O czym jest ta przestrzeń?" "%1$d Przestrzeń" "%1$d Przestrzenie" @@ -341,12 +382,13 @@ Powód: %1$s." "Rozpoczynanie czatu…" "Naklejka" "Sukces" + "Polecane" "Sugestie" "Synchronizuję" - "System" "Tekst" "Informacje stron trzecich" "Wątek" + "Wątki" "Temat" "O czym jest ten pokój?" "Nie można odszyfrować" @@ -377,13 +419,19 @@ Powód: %1$s." "Wiadomość głosowa" "Oczekiwanie…" "Oczekiwanie na tę wiadomość" + "Czekam na lokalizację na żywo…" + "Każdy może zobaczyć historię" "Ty" - "Tożsamość %1$s została zresetowana. %2$s" + "%1$s (%2$s) udostępnił tę wiadomość, kiedy nie było Cię w pokoju, gdy została wysłana." + "%1$s udostępnił tę wiadomość, kiedy nie było Cię w pokoju, gdy została wysłana." + "Ten pokój został skonfigurowany tak, aby nowi członkowie mogli czytać historię czatu. %1$s" + "Tożsamość cyfrowa %1$s została zresetowana. %2$s" "Tożsamość %1$s %2$s została zresetowana. %3$s" "(%1$s)" - "Tożsamość %1$s została zresetowana" - "Tożsamość %1$s %2$s została zresetowana. %3$s" + "Tożsamość %1$s została zresetowana." + "Tożsamość %1$s %2$s została zresetowana. %3$s" "Wycofaj weryfikację" + "Zezwól na dostęp" "Link %1$s prowadzi Cię do innej witryny %2$s Czy na pewno chcesz kontynuować?" @@ -413,6 +461,7 @@ Czy na pewno chcesz kontynuować?" "%1$s nie mógł uzyskać dostępu do Twojej lokalizacji. Spróbuj ponownie później." "Nie udało się przesłać Twojej wiadomości głosowej." "Pokój już nie istnieje lub zaproszenie nie jest już ważne." + "Włącz GPS, aby uzyskać dostęp do funkcji opartych na lokalizacji." "Nie znaleziono wiadomości" "%1$s nie uzyskało uprawnienia do dostępu do twojej lokalizacji. Możesz włączyć dostęp w Ustawieniach." "%1$s nie ma uprawnień dostępu do Twojej lokalizacji. Włącz dostęp poniżej." @@ -424,6 +473,9 @@ Czy na pewno chcesz kontynuować?" "Przepraszamy, wystąpił błąd" "🔐️ Dołącz do mnie na %1$s" "Hej, porozmawiajmy na %1$s: %2$s" + "Udostępnianie lokalizacji na żywo" + "Udostępnianie lokalizacji w toku" + "Lokalizacja na żywo %1$s" "%1$s Android" "Wstrząśnij gniewnie, aby zgłosić błąd" "Zrzut ekranu" @@ -431,6 +483,14 @@ Czy na pewno chcesz kontynuować?" "Opcje" "Usuń %1$s" "Ustawienia" + "Nikt nie udostępnia swojej lokalizacji" + "Udostępnianie lokalizacji na żywo" + + "%1$d osoba" + "%1$d osoby" + "%1$d osób" + + "Na mapie" "Nie udało się wybrać multimediów. Spróbuj ponownie." "Naciśnij wiadomość i wybierz “%1$s”, aby dołączyć tutaj." "Przypinaj ważne wiadomości, aby można było je łatwo znaleźć" @@ -456,6 +516,7 @@ Czy na pewno chcesz kontynuować?" "Wiadomość w %1$s" "Rozwiń" "Zmniejsz" + "Udostępnianie lokalizacji na żywo" "Już oglądasz ten pokój!" "%1$s z %2$s" "%1$s przypiętych wiadomości" @@ -467,11 +528,15 @@ Czy na pewno chcesz kontynuować?" "Otwórz w Apple Maps" "Otwórz w Google Maps" "Otwórz w OpenStreetMap" - "Udostępnij tę lokalizację" + "Udostępnij wybraną lokalizację" + "Opcje udostępniania" "Przestrzenie, które stworzyłeś lub do których dołączyłeś." "%1$s • %2$s" + "Utwórz przestrzeń, aby organizować pokoje" "Przestrzeń %1$s" "Przestrzenie" + "Udostępnianie %1$s" + "Na mapie" "Wiadomość nie została wysłana, ponieważ tożsamość %1$s została zresetowana." "Wiadomość nie została wysłana, ponieważ %1$s nie zweryfikował wszystkich urządzeń." "Wiadomość nie została wysłana, ponieważ nie zweryfikowałeś jednego lub więcej swoich urządzeń." @@ -482,5 +547,5 @@ Czy na pewno chcesz kontynuować?" "Musisz zweryfikować to urządzenie, aby uzyskać dostęp do historii wiadomości" "Nie masz uprawnień do tej wiadomości" "Nie można odszyfrować wiadomości" - "Wiadomość została zablokowana, ponieważ urządzenie nie zostało zweryfikowane lub nadawca musi zweryfikować Twoją tożsamość." + "Ta wiadomość została zablokowana, ponieważ urządzenie nie zostało zweryfikowane lub nadawca musi zweryfikować Twoją tożsamość." diff --git a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml index 49351c6b64..f35aca5a58 100644 --- a/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt-rBR/translations.xml @@ -200,7 +200,6 @@ "Saiu da sala" "Saiu do espaço" "Convite recusado" - "Escuro" "Erro de descriptografia" "Descrição" "Opções de desenvolvedor" @@ -238,7 +237,6 @@ Motivo:​ %1$s." "Este ID Matrix não foi encontrado, então o convite pode não ser recebido" "Saindo da sala" "Saindo do espaço" - "Claro" "Linha copiada para a área de transferência" "Link copiado para área de transferência" "Vincular novo dispositivo" @@ -300,7 +298,6 @@ Motivo:​ %1$s." "%1$d respostas" "Respondendo a %1$s" - "Denunciar um bug" "Relatar um problema" "Relatório enviado" "Editor de rich text" @@ -351,7 +348,6 @@ Motivo:​ %1$s." "Sugerido" "Sugestões" "Sincronizando" - "Sistema" "Texto" "Comunicados de terceiros" "Tópico" diff --git a/libraries/ui-strings/src/main/res/values-pt/translations.xml b/libraries/ui-strings/src/main/res/values-pt/translations.xml index dd15875590..0acc939565 100644 --- a/libraries/ui-strings/src/main/res/values-pt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-pt/translations.xml @@ -195,7 +195,6 @@ "Saíste da sala" "Saíste do espaço" "Convite rejeitado" - "Escuro" "Erro de decifragem" "Descrição" "Opções de programador" @@ -233,7 +232,6 @@ Razão: %1$s." "Não foi possível encontrar este ID Matrix, portanto o convite pode não ser recebido." "A sair da sala" "A sair do espaço" - "Claro" "Linha copiada para a área de transferência" "Ligação copiada para a área de transferência" "A carregar…" @@ -291,7 +289,6 @@ Razão: %1$s." "%1$d respostas" "Em resposta a %1$s" - "Comunicar falha" "Comunicar um problema" "Denúncia submetida" "Editor de texto rico" @@ -335,7 +332,6 @@ Razão: %1$s." "Sucesso" "Sugestões" "A sincronizar…" - "Sistema" "Texto" "Avisos de terceiros" "Tópico" diff --git a/libraries/ui-strings/src/main/res/values-ro/translations.xml b/libraries/ui-strings/src/main/res/values-ro/translations.xml index f47d43b47e..35930b694e 100644 --- a/libraries/ui-strings/src/main/res/values-ro/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ro/translations.xml @@ -1,6 +1,7 @@ "Adăugați o reacție: %1$s" + "Adresă" "Imagine de profil" "Micșorați câmpul mesajului" "Ștergere" @@ -197,7 +198,6 @@ "Ați parăsit camera" "S-a părăsit spațiul" "Invitația a fost refuzată" - "Întunecat" "Eroare de decriptare" "Descriere" "Opțiuni programator" @@ -235,7 +235,6 @@ Motiv:%1$s." "Nu am putut valida ID-ul Matrix al acestui utilizator. Este posibil ca invitația să nu fi fost trimisă." "Se părăsește conversația" "Se părăsește spațiul" - "Deschis" "Linie copiată în clipboard" "Linkul a fost copiat în clipboard" "Conectați un dispozitiv nou" @@ -300,7 +299,6 @@ Motiv:%1$s." "%1$d răspunsuri" "Răspuns pentru %1$s" - "Raportați o eroare" "Raportați o problemă" "Raport trimis" "Editor text avansat" @@ -347,7 +345,6 @@ Motiv:%1$s." "Succes" "Sugestii" "Se sincronizează…" - "Sistem" "Text" "Notificări despre software de la terți" "Fir" diff --git a/libraries/ui-strings/src/main/res/values-ru/translations.xml b/libraries/ui-strings/src/main/res/values-ru/translations.xml index bb423b5b10..26e1dcfe8d 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -195,7 +195,6 @@ "Расширенные настройки" "изображение" "Аналитика" - "Синхронизация уведомлений…" "Вы покинули комнату" "Вы вышли из сессии" "Внешний вид" @@ -213,7 +212,6 @@ "Покинул комнату" "Покинуть пространство" "Приглашение отклонено" - "Темная" "Ошибка расшифровки" "Описание" "Для разработчиков" @@ -239,6 +237,7 @@ "Ошибка" "Избранное" "Избранное" + "Синхронизация уведомлений…" "Файл" "Файл удалён" "Файл сохранен" @@ -252,7 +251,6 @@ "Идентификатор Matrix ID не найден, приглашение может быть не получено." "Покидаем комнату" "Покидаем пространство" - "Светлое" "Строка скопирована в буфер обмена" "Ссылка скопирована в буфер обмена" "Привязать новое устройство" @@ -323,7 +321,6 @@ "%1$d ответов" "Отвечает %1$s" - "Сообщить об ошибке" "Сообщить о проблеме" "Отчет отправлен" "Форматирование" @@ -380,7 +377,6 @@ "Рекомендуемые" "Предложения" "Синхронизация" - "Системное" "Текст" "Уведомления о третьих лицах" "Обсуждение" diff --git a/libraries/ui-strings/src/main/res/values-sk/translations.xml b/libraries/ui-strings/src/main/res/values-sk/translations.xml index e154093ddb..11f4b22005 100644 --- a/libraries/ui-strings/src/main/res/values-sk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sk/translations.xml @@ -1,6 +1,7 @@ "Pridať reakciu: %1$s" + "Adresa" "Obrázok" "Minimalizovať textové pole správy" "Vymazať" @@ -27,6 +28,7 @@ "Pozastaviť" "Hlasová správa, dĺžka:%1$s, aktuálna pozícia: %2$s" "Pole PIN" + "Pripnuté miesto" "Prehrať" "Anketa" "Ukončená anketa" @@ -47,6 +49,8 @@ "Vyžaduje sa časovo obmedzená akcia, na overenie máte jednu minútu" "Zobraziť heslo" "Začať hovor" + "Začať videohovor" + "Začať hlasový hovor" "Opustená miestnosť" "Profilový obrázok" "Používateľské menu" @@ -157,8 +161,8 @@ "Zdieľať odkaz" "Zobraziť" "Prihláste sa znova" - "Odhlásiť sa" - "Napriek tomu sa odhlásiť" + "Odstrániť toto zariadenie" + "Napriek tomu odstrániť toto zariadenie" "Preskočiť" "Spustiť" "Začať konverzáciu" @@ -202,7 +206,6 @@ "Opustil/a miestnosť" "Opustil priestor" "Pozvánka bola odmietnutá" - "Tmavý" "Chyba dešifrovania" "Popis" "Možnosti pre vývojárov" @@ -240,7 +243,6 @@ Dôvod: %1$s." "Toto Matrix ID sa nedá nájsť, takže pozvánka nemusí byť prijatá." "Opustenie miestnosti" "Opúšťanie priestoru" - "Svetlý" "Riadok skopírovaný do schránky" "Odkaz bol skopírovaný do schránky" "Prepojiť nové zariadenie" @@ -306,7 +308,6 @@ Dôvod: %1$s." "%1$d odpovedí" "Odpoveď na %1$s" - "Nahlásiť chybu" "Nahlásiť problém" "Nahlásenie bolo odoslané" "Rozšírený textový editor" @@ -360,7 +361,6 @@ Dôvod: %1$s." "Navrhované" "Návrhy" "Synchronizuje sa" - "Systém" "Text" "Oznámenia tretích strán" "Vlákno" @@ -487,7 +487,7 @@ Naozaj chcete pokračovať?" "Otvoriť v Apple Maps" "Otvoriť v Mapách Google" "Otvoriť v OpenStreetMap" - "Zdieľajte túto polohu" + "Zdieľajte vybranú polohu" "Priestory, ktoré ste vytvorili alebo ku ktorým ste sa pripojili." "%1$s • %2$s" "Vytvorte priestory na usporiadanie miestností" diff --git a/libraries/ui-strings/src/main/res/values-sv/translations.xml b/libraries/ui-strings/src/main/res/values-sv/translations.xml index dfcd514209..28dd63d425 100644 --- a/libraries/ui-strings/src/main/res/values-sv/translations.xml +++ b/libraries/ui-strings/src/main/res/values-sv/translations.xml @@ -187,7 +187,6 @@ "Begäran avbruten" "Lämnade rummet" "Inbjudan avvisad" - "Mörkt" "Avkrypteringsfel" "Beskrivning" "Utvecklaralternativ" @@ -224,7 +223,6 @@ Anledning:%1$s." "Installera APK" "Det här Matrix-ID:t kan inte hittas, så inbjudan kanske inte tas emot." "Lämnar rummet" - "Ljust" "Rad kopierad till klippbordet" "Länk kopierad till klippbordet" "Laddar …" @@ -281,7 +279,6 @@ Anledning:%1$s." "%1$d svar" "Svarar till %1$s" - "Rapportera en bugg" "Rapportera ett problem" "Rapport inskickad" "Riktextredigerare" @@ -323,7 +320,6 @@ Anledning:%1$s." "Lyckades" "Förslag" "Synkar" - "System" "Text" "Meddelanden från tredje part" "Tråd" diff --git a/libraries/ui-strings/src/main/res/values-tr/translations.xml b/libraries/ui-strings/src/main/res/values-tr/translations.xml index d92daa6527..d500b57507 100644 --- a/libraries/ui-strings/src/main/res/values-tr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-tr/translations.xml @@ -175,7 +175,6 @@ "İstek iptal edildi" "Sol oda" "Davet reddedildi" - "Koyu" "Şifre çözme hatası" "Geliştirici seçenekleri" "Cihaz Kimliği" @@ -211,7 +210,6 @@ Neden: %1$s." "APK\'yı yükleyin" "Bu Matrix Kimliği bulunamıyor, bu nedenle davet alınmayabilir." "Odadan ayrılma" - "Aydınlık" "Metin panoya kopyalandı" "Bağlantı panoya kopyalandı" "Yükleniyor…" @@ -264,7 +262,6 @@ Neden: %1$s." "Kurtarma anahtarı" "Yenileniyor…" "Cevaplamak için %1$s" - "Hata bildir" "Sorun bildir" "Rapor gönderildi" "Zengin metin editörü" @@ -296,7 +293,6 @@ Neden: %1$s." "Başarılı" "Öneriler" "Senkronizasyon" - "Sistem" "Metin" "Üçüncü taraf bildirimleri" "Konu" diff --git a/libraries/ui-strings/src/main/res/values-uk/translations.xml b/libraries/ui-strings/src/main/res/values-uk/translations.xml index 835ded33f9..d7b18bf1ae 100644 --- a/libraries/ui-strings/src/main/res/values-uk/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uk/translations.xml @@ -1,6 +1,7 @@ "Додати реакцію: %1$s" + "Адреса" "Аватар" "Згорнути поле тексту повідомлення" "Видалити" @@ -14,6 +15,7 @@ "Подробиці шифрування" "Розгорнути текстове поле повідомлення" "Cховати пароль" + "Інформація" "Приєднатися до виклику" "Перейти вниз" "Перемістити карту до мого місця перебування" @@ -27,9 +29,12 @@ "Пауза" "Голосове повідомлення, тривалість: %1$s, поточна позиція: %2$s" "Поле PIN-коду" + "Закріплена локація" "Відтворити" + "Швидкість програвання" "Опитування" "Опитування завершено" + "QR-код" "Реагувати з%1$s" "Відреагувати іншими смайликами" "Прочитано %1$s та %2$s" @@ -44,9 +49,13 @@ "Прибрати реакцію %1$s" "Аватар кімнати" "Надіслати файли" + "Локація відправника" "Необхідно виконати дію, обмежену в часі, у вас є одна хвилина для верифікації" + "Налаштування, потрібні дії" "Показати пароль" "Розпочати виклик" + "Розпочати відеодзвінок" + "Розпочати голосовий дзвінок" "Кімната більше не використовується" "Аватар користувача" "Меню користувача" @@ -64,6 +73,7 @@ "Зателефонувати" "Скасувати" "Скасувати наразі" + "Вибрати файл" "Вибрати фото" "Очистити" "Закрити" @@ -83,18 +93,22 @@ "Деактивувати обліковий запис" "Відхилити" "Відхилити та заблокувати" + "Видалити" + "Видалити обліковий запис" "Видалити опитування" "Скасувати вибір усіх" "Вимкнути" "Відкинути" "Відхилити" "Готово" + "Завантажити" "Редагувати" "Редагувати підпис" "Редагувати опитування" "Увімкнути" "Завершити опитування" "Введіть PIN-код" + "Дізнатися про публічні простори" "Завершити" "Забули пароль?" "Переслати" @@ -115,6 +129,7 @@ "Вийти з простору" "Завантажити ще" "Керування обліковим записом" + "Керування обліковим записом і пристроями" "Керування пристроями" "Керувати кімнатами" "Написати" @@ -154,6 +169,7 @@ "Надіслати голосове повідомлення" "Поділитися" "Поділитися посиланням" + "Ділитися місцезнаходженням у реальному часі" "Показати" "Увійдіть знову" "Вийти" @@ -164,6 +180,7 @@ "Почати спочатку" "Почати верифікацію" "Натисніть, щоб завантажити мапу" + "Зупинити" "Зробити фото" "Торкніться, щоб переглянути параметри" "Перекласти" @@ -191,7 +208,9 @@ "Бета-версія" "Заблоковані користувачі" "Бульбашки" + "Дзвінок відхилено" "Виклик розпочато" + "Ви відхилили дзвінок" "Резервне копіювання бесіди" "Скопійовано до буферу обміну" "Авторське право" @@ -199,8 +218,8 @@ "Створення простору…" "Запит скасовано" "Виходить з кімнати" + "Вийшов із простору" "Запрошення відхилено" - "Темна" "Помилка розшифрування" "Опис" "Налаштування розробника" @@ -216,6 +235,7 @@ "Порожній файл" "Шифрування" "Шифрування ввімкнено" + "Завершується о %1$s" "Введіть свій PIN-код" "Помилка" "Сталася помилка, ви можете не отримувати сповіщення про нові повідомлення. Усуньте неполадки зі сповіщеннями в налаштуваннях. @@ -225,6 +245,7 @@ "Помилка" "Обране" "Обране" + "Синхронізація сповіщень…" "Файл" "Файл видалено" "Файл збережено" @@ -238,10 +259,11 @@ "Цей Matrix-ID не знайдено, тому запрошення може не бути отримано." "Вихід з кімнати" "Вихід з простору" - "Світла" "Рядок скопійовано до буфера обміну" "Посилання скопійовано в буфер обміну" "Під\'єднати новий пристрій" + "Місцезнаходження в реальному часі" + "Показ місцеперебування наживо завершено" "Завантаження" "Завантаження наступних…" @@ -270,6 +292,7 @@ "Не в мережі" "Ліцензії відкритого коду" "або" + "Інші варіанти" "Пароль" "Люди" "Постійне посилання" @@ -288,8 +311,10 @@ "Приготування…" "Політика конфіденційності" + "Приватний" "Приватна кімната (тільки за запрошенням)" "Приватний простір" + "Публічний" "Загальнодоступна кімната" "Загальнодоступний простір" "Реакція" @@ -304,7 +329,6 @@ "%1$d відповідей" "Відповідь %1$s" - "Повідомити про ваду" "Повідомити про проблему" "Звіт подано" "Багатоформатний текстовий редактор" @@ -325,6 +349,11 @@ "Безпека" "Переглянули" "Вибрати обліковий запис" + + "%1$d вибраний" + "%1$d вибрані" + "%1$d вибрано" + "Надіслати до" "Надсилання…" "Не вдалося надіслати" @@ -334,12 +363,16 @@ "Сервер недоступний" "URL-адреса сервера" "Налаштування" + "Поділитися простором" "Нові учасники бачать історію" + "Поділитися місцезнаходженням в реальному часі" "Поширене розташування" + "Простір спільного користування" "Вихід" "Щось пішло не так" "Ми зіткнулися з проблемою. Будь ласка, повторіть спробу." "Простір" + "Учасники простору" "Про що цей простір?" "%1$d простір" @@ -349,12 +382,13 @@ "Початок бесіди…" "Наліпка" "Успіх" + "Запропоновано" "Пропозиції" "Синхронізація" - "Системна" "Текст" "Повідомлення третіх сторін" "Гілка" + "Гілки" "Тема" "Про що ця кімната?" "Неможливо розшифрувати" @@ -385,14 +419,19 @@ "Голосове повідомлення" "Очікування…" "Чекаємо на це повідомлення" + "Очікування геолокації…" "Будь-хто може переглянути історію" "Ви" + "%1$s (%2$s) поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали." + "%1$s поділився цим повідомленням, оскільки вас не було в кімнаті, коли його надіслали." + "Згідно із налаштувань цієї кімнати, нові учасники можуть переглядати історію. %1$s" "Ідентичність %1$s скинуто. %2$s" "Ідентичність %1$s %2$s скинуто. %3$s" "(%1$s)" "Ідентичність %1$s скинуто." "Ідентичність %1$s %2$s скинуто. %3$s" "Відкликати верифікацію" + "Надати доступ" "Посилання %1$s спрямовує вас на інший сайт %2$s Ви впевнені, що хочете продовжити?" @@ -422,6 +461,7 @@ "%1$s не вдалося отримати доступ до вашого розташування. Повторіть спробу пізніше." "Не вдалося завантажити голосове повідомлення." "Кімната більше не існує або запрошення не чинне." + "Будь ласка, увімкніть GPS, щоб отримати доступ до функцій, що використовують геолокацію." "Повідомлення не знайдено" "%1$s не має дозволу на доступ до вашого розташування. Увімкнути доступ можна в Налаштуваннях." "%1$s не має дозволу на доступ до вашого розташування. Увімкніть доступ нижче." @@ -440,6 +480,14 @@ "Варіанти" "Вилучити %1$s" "Налаштування" + "Ніхто не ділиться своєю геопозицією" + "Обмін геопозицією" + + "%1$d особа" + "%1$d осіб" + "%1$d осіб" + + "На карті" "Не вдалося вибрати медіафайл, спробуйте ще раз." "Натисніть на повідомлення і виберіть \"%1$s\", щоб додати його сюди." "Закріпіть важливі повідомлення, щоб їх можна було легко знайти" @@ -465,6 +513,7 @@ "Повідомлення в %1$s" "Розгорнути" "Згорнути" + "Спільний доступ до місцезнаходження у реальному часі" "Уже переглядаєте цю кімнату!" "%1$s із %2$s" "%1$s закріплених повідомлень" @@ -477,10 +526,14 @@ "Відкрити в Картах Google" "Відкрити в OpenStreetMap" "Поділитися цим місцем перебування" + "Налаштування обміну геопозицією" "Простори, які ви створили або до яких приєдналися." "%1$s • %2$s" + "Створіть простори для організації кімнат" "Простір %1$s" "Простори" + "Надано доступ %1$s" + "На карті" "Повідомлення не надіслано, оскільки підтверджену особистість %1$s скинуто." "Повідомлення не надіслано, оскільки %1$s перевірив не всі пристрої." "Повідомлення не надіслано, оскільки ви не підтвердили один або кілька своїх пристроїв." diff --git a/libraries/ui-strings/src/main/res/values-ur/translations.xml b/libraries/ui-strings/src/main/res/values-ur/translations.xml index 8e9c0fb3be..accba4556c 100644 --- a/libraries/ui-strings/src/main/res/values-ur/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ur/translations.xml @@ -141,7 +141,6 @@ "حقوقِ طبع و نشر" "کمرہ تخلیق کررہاہے…" "کمرہ چھوڑ لیا" - "اندھیرا" "رمزکشائی کی خرابی" "مطور اختیارات" "براہ راست گفتگو" @@ -168,7 +167,6 @@ "APK تنصیب کریں" "یہ میٹرکس شناخت نہیں مل سکتی، تو ہو سکتا ہے کہ دعوت نامہ موصول نہ ہو۔" "کمرہ چھوڑنا" - "روشنی" "ربط تختہ تراشہ پر نقل کردا گیا" "لاد رہا ہے…" @@ -212,7 +210,6 @@ "بازیابی کی کلید" "تاکہ کر رہا ہے…" "%1$s کا جواب دے رہے ہیں" - "ایک خطاء کی اطلاع دیں" "کسی مسئلے کی اطلاع دیں" "گزارش جمع ہوگئی" "امیر مدیرِ متن" @@ -241,7 +238,6 @@ "کامیابی" "تجاویز" "ہمسات سازی" - "نظام" "متن" "فریق ثالث کے اشعارات" "دھاگہ" diff --git a/libraries/ui-strings/src/main/res/values-uz/translations.xml b/libraries/ui-strings/src/main/res/values-uz/translations.xml index 2542de084e..63e1756a23 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -193,7 +193,6 @@ "Kengaytirilgan sozlamalar" "rasm" "Analitika" - "Bildirishnomalar sinxronlanmoqda…" "Siz xonani tark etdingiz" "Siz sessiyadan chiqdingiz" "Ko\'rinish" @@ -211,7 +210,6 @@ "Xonani tark etdi" "Tar etilgan maydon" "Taklif rad etildi" - "Tungi" "Shifrni ochish xatosi" "Tavsif" "Dasturchi variantlari" @@ -237,6 +235,7 @@ Sababi:%1$s." "Xatolikka uchradi" "Sevimli" "Sevimli" + "Bildirishnomalar sinxronlanmoqda…" "Fayl" "Fayl o\'chirildi" "Fayl saqlandi" @@ -250,7 +249,6 @@ Sababi:%1$s." "Ushbu Matrix identifikatori topilmadi, shuning uchun taklif qabul qilinmasligi mumkin." "Xonadan chiqish" "Maydonni tark etish" - "Nur" "Satr vaqtinchalik xotiraga nusxalandi" "Havola vaqtinchalik xotiraga nusxalandi" "Yangi qurilmani ulang" @@ -317,7 +315,6 @@ Sababi:%1$s." "%1$d ta javob" "%1$sga Javob berilmoqda" - "Xato haqida xabar bering" "Muammo haqida xabar bering" "Hisobot topshirildi" "Boy matn muharriri" @@ -371,7 +368,6 @@ Sababi:%1$s." "Tavsiya etilgan" "Tavsiyalar" "Sinxronlash" - "Tizim" "Matn" "Uchinchi tomon bildirishnomalari" "Ip" @@ -410,6 +406,7 @@ Sababi:%1$s." "Tarixni hamma ko‘rishi mumkin" "Siz" "%1$s (%2$s) bu xabarni ulashdi, chunki u yuborilganda siz xonada emas edingiz." + "%1$s bu xabar yuborilgan paytda siz xonada bo‘lmaganingiz uchun uni ulashdi." "Siz yuborgan xabarlar bu xonaga taklif qilingan yangi a’zolarga ulashiladi. %1$s" "%1$sning raqamli identifikatori qayta tiklandi.%2$s" "%1$sning%2$s raqamli identifikatsiya qayta tiklandi.%3$s" diff --git a/libraries/ui-strings/src/main/res/values-vi/translations.xml b/libraries/ui-strings/src/main/res/values-vi/translations.xml index 9a450117ac..5cfbe26fba 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -191,7 +191,6 @@ "Cài đặt nâng cao" "một hình ảnh" "Phân tích" - "Đang đồng bộ thông báo…" "Bạn rời phòng" "Bạn đã bị đăng xuất" "Giao diện" @@ -209,7 +208,6 @@ "Đã rời khỏi phòng" "Rời khỏi không gian" "Lời mời bị từ chối" - "Tối" "Lỗi khi giải mã" "Mô tả" "Tùy chọn nhà phát triển" @@ -235,6 +233,7 @@ Lý do: %1$s ." "Thất bại" "Yêu thích" "Được yêu thích" + "Đang đồng bộ thông báo…" "Tập tin" "Tệp đã bị xóa" "Tệp đã được lưu" @@ -248,7 +247,6 @@ Lý do: %1$s ." "Không tìm thấy Matrix ID này, nên lời mời có thể chưa được nhận." "Rời khỏi phòng" "Rời khỏi không gian" - "Sáng" "Đã sao chép dòng" "Đã chép liên kết vào bộ nhớ tạm" "Liên kết thiết bị mới" @@ -310,7 +308,6 @@ Lý do: %1$s ." "%1$d trả lời" "Đang trả lời cho %1$s" - "Báo cáo lỗi" "Báo cáo sự cố" "Đã gửi báo cáo" "Trình soạn thảo văn bản nâng cao" @@ -360,7 +357,6 @@ Lý do: %1$s ." "Gợi ý" "Gợi ý" "Đang đồng bộ" - "Hệ thống" "Văn bản" "Thông báo từ bên thứ ba" "Chủ đề" diff --git a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml index 11eb111b49..71159b78e4 100644 --- a/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh-rTW/translations.xml @@ -191,7 +191,6 @@ "進階設定" "影像" "分析" - "正在同步通知……" "您離開聊天室" "您已登出工作階段" "外觀" @@ -209,7 +208,6 @@ "已離開聊天室" "離開空間" "邀請被拒絕" - "深色" "解密錯誤" "描述" "開發者選項" @@ -235,6 +233,7 @@ "失敗" "我的最愛" "我的最愛" + "正在同步通知……" "檔案" "檔案已刪除" "檔案已儲存" @@ -248,7 +247,6 @@ "找不到此 Matrix ID,因此可能沒有人會收到邀請。" "正在離開聊天室" "離開空間" - "淺色" "行已複製到剪貼簿" "連結已複製到剪貼簿" "連結新裝置" @@ -311,7 +309,6 @@ "%1$d 個回覆" "正在回覆%1$s" - "回報程式錯誤" "回報問題" "已遞交報告" "格式化文字編輯器" @@ -362,7 +359,6 @@ "已建議" "建議" "同步中" - "系統" "文字" "第三方通知" "討論串" diff --git a/libraries/ui-strings/src/main/res/values-zh/translations.xml b/libraries/ui-strings/src/main/res/values-zh/translations.xml index 974e91b530..9cea16d2f0 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -13,6 +13,7 @@ "加密详情" "展开消息文本框" "隐藏密码" + "信息" "加入通话" "跳转到底部" "将地图移动到我的位置" @@ -67,6 +68,7 @@ "通话" "取消" "暂时取消" + "选择文件" "选择照片" "清除" "关闭" @@ -125,7 +127,7 @@ "管理账户与设备" "管理设备" "管理房间" - "发送消息给" + "发送消息" "最小化" "下一步" "否" @@ -194,7 +196,6 @@ "高级设置" "一张图片" "分析" - "正在同步通知…" "你离开了房间" "你已注销会话" "外观" @@ -214,7 +215,6 @@ "离开房间" "离开空间" "邀请已拒绝" - "深色" "解密错误" "描述" "开发者选项" @@ -240,6 +240,7 @@ "失败" "收藏" "已收藏" + "正在同步通知…" "文件" "文件已删除" "文件已保存" @@ -253,7 +254,6 @@ "找不到此 Matrix ID,因此可能无法收到邀请。" "正在离开房间" "正在离开空间" - "浅色" "链接已复制到剪贴板" "链接已复制到剪贴板" "关联新设备" @@ -316,7 +316,6 @@ "%1$d 个回复" "正在回复 %1$s" - "报告 bug" "报告问题" "报告已提交" "富文本编辑器" @@ -367,7 +366,6 @@ "建议" "建议" "正在同步" - "系统" "文本" "第三方通知" "消息列" @@ -456,6 +454,8 @@ "抱歉,发生了错误" "🔐️ 在 %1$s 中与我一起" "嗨!请通过 %1$s 与我联系:%2$s" + "正在共享实时位置" + "位置共享正在进行" "%1$s Android" "摇一摇以报告 bug" "屏幕截图" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index cdb3c52e6a..ee0f51000a 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -199,7 +199,6 @@ "Advanced settings" "an image" "Analytics" - "Syncing notifications…" "You left the room" "You were logged out of the session" "Appearance" @@ -219,7 +218,6 @@ "Left room" "Left space" "Invite declined" - "Dark" "Decryption error" "Description" "Developer options" @@ -245,6 +243,7 @@ Reason: %1$s." "Failed" "Favourite" "Favourited" + "Syncing notifications…" "File" "File deleted" "File saved" @@ -258,7 +257,6 @@ Reason: %1$s." "This Matrix ID can\'t be found, so the invite might not be received." "Leaving room" "Leaving space" - "Light" "Line copied to clipboard" "Link copied to clipboard" "Link new device" @@ -325,7 +323,6 @@ Reason: %1$s." "%1$d replies" "Replying to %1$s" - "Report a bug" "Report a problem" "Report submitted" "Rich text editor" @@ -379,7 +376,6 @@ Reason: %1$s." "Suggested" "Suggestions" "Syncing" - "System" "Text" "Third-party notices" "Thread" @@ -468,6 +464,9 @@ Are you sure you want to continue?" "Sorry, an error occurred" "🔐️ Join me on %1$s" "Hey, talk to me on %1$s: %2$s" + "Live Location Sharing" + "Location sharing in progress" + "%1$s Live Location" "%1$s Android" "Rageshake to report bug" "Screenshot" diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml deleted file mode 100644 index ba6c431d8b..0000000000 --- a/libraries/ui-strings/src/main/res/values/temporary.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - "Black" - diff --git a/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt b/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt index 9d471f7a6d..9d41b0da92 100644 --- a/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt +++ b/libraries/voicerecorder/impl/src/main/kotlin/io/element/android/libraries/voicerecorder/impl/audio/DefaultEncoder.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.voicerecorder.impl.audio import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.Provider import io.element.android.libraries.di.RoomScope import io.element.android.opusencoder.OggOpusEncoder import timber.log.Timber @@ -20,7 +19,7 @@ import java.io.File */ @ContributesBinding(RoomScope::class) class DefaultEncoder( - private val encoderProvider: Provider, + private val encoderProvider: () -> OggOpusEncoder, config: AudioConfig, ) : Encoder { private val bitRate = config.bitRate diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index fa197e4a08..a3de4327b4 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -45,7 +45,7 @@ private const val versionMonth = 5 * Release number in the month. Value must be in [0,99]. * Do not update this value. it is updated by the release script. */ -private const val versionReleaseNumber = 0 +private const val versionReleaseNumber = 1 object Versions { /** diff --git a/screenshots/de/appnav.root_RootView_Day_0_de.png b/screenshots/de/appnav.root_RootView_Day_0_de.png index 7f70b90751..2d0d9fab03 100644 --- a/screenshots/de/appnav.root_RootView_Day_0_de.png +++ b/screenshots/de/appnav.root_RootView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa11b2165af4a12cd518fb3f9a06b91d9ce87b468705efc7a962bf34a8278fac -size 26284 +oid sha256:c3082552bf96131ddba157697bb254e22d6277537759c32dfabb56a2e99a9138 +size 27116 diff --git a/screenshots/de/appnav.root_RootView_Day_1_de.png b/screenshots/de/appnav.root_RootView_Day_1_de.png index e1796d211b..6d1c994b27 100644 --- a/screenshots/de/appnav.root_RootView_Day_1_de.png +++ b/screenshots/de/appnav.root_RootView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35a9ac561c2546fd94121cb0c80e1f5be1fe147f425be4d087b647ae0f204afd -size 29986 +oid sha256:f9231272736124f1e54a3422310d2dd5c7ad81e850548886062df61de36165c4 +size 30868 diff --git a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png index 79a282bf32..5fb0408a49 100644 --- a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png +++ b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:141bf23853b7ba97cffd4d54e9e0a48843d0a49e7f6d6a91c41f110d2df1c7dd -size 24180 +oid sha256:d20416987d2485431b66ebb29af1f03efa2e04da7ef5875eda62d7c5e187052b +size 24828 diff --git a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png index bc89b471f2..4aa0388c8a 100644 --- a/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png +++ b/screenshots/de/features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a39d0a1c752533bfb097ad1d2c59978123545ee76259e26efe6e3fbae209db69 -size 31441 +oid sha256:62d531d6b01266019e2fa686321e93d64bcffd5b1786f7ad4efac83fcc2a2fc5 +size 32141 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png new file mode 100644 index 0000000000..048facf45b --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b4ead892d27f2eb5fd7c9319e3c954ab2ae57c68180e08b30c07741c53cadda +size 35383 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png new file mode 100644 index 0000000000..af1fe3af55 --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b481b2bafe288542d25c301aa568fdbd9d63170b1c59b01fdacacc69d0395b3 +size 17352 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png new file mode 100644 index 0000000000..28afdb624e --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_8_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6f6d2946d194ba97c64e6749b1f9d8bf4ce52e685d06631cf22b47e156791d1 +size 41526 diff --git a/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png new file mode 100644 index 0000000000..9c540f1299 --- /dev/null +++ b/screenshots/de/features.lockscreen.impl.unlock_PinUnlockView_Day_9_de.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b74c5fd9cb084ca2c391ea65dea23ecc027d1206510841ada0d28d5f6674995 +size 32940 diff --git a/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png b/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png index 67fec85a88..b3f6706cda 100644 --- a/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png +++ b/screenshots/de/features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68d468cf24f004f75b5f0d0ab21e4576941749b32a6780b074fce5ba6e7e06c0 -size 56172 +oid sha256:29fb6c5ccbc3fc1196fbccc4ce18d10668ae47733ecfcc454354ff231cac0f10 +size 56030 diff --git a/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png b/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png index 72c99d1da9..3ece744fcb 100644 --- a/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png +++ b/screenshots/de/features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b10f43a24d80689ee7c929eb5c530b544891cb0dce63ab9bbb4618f999fbd3cd -size 6226 +oid sha256:cbc7e8874d0a3c25aa0e6036c1ffc365c5407d79b011e5321821691315e98d3a +size 6223 diff --git a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png index 75eb3ccc78..abb112a538 100644 --- a/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png +++ b/screenshots/de/features.messages.impl.timeline_TimelineView_Day_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68cef5541309a99a95f5004cbdcb4d091a70f68c142de2ff78deb710c521ea30 -size 69820 +oid sha256:4c119e44d9f51d0b4786f06092d3d0138ef69b363c43303164b0aac0629b324e +size 69840 diff --git a/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png b/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png index 99f0c161e8..2190897314 100644 --- a/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png +++ b/screenshots/de/features.messages.impl.topbars_MessagesViewTopBar_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d23534a940951085437a3c739b58d515a968869227db794a149b5066abe21800 -size 58473 +oid sha256:f952ad332aea788e87445b304894f0acf77a6ca5498d67584ab4e727cbb16eb4 +size 58055 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png index 99f738df12..9827329bbd 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe130f936313191f602331d5b1a08dd025da47a66ce23dd71cee0665e951a3ac -size 44506 +oid sha256:ece0f3e49ca489a67aa7a489bc2d7e4f35a99cff4e4f2df3f7ab480965b3f972 +size 44150 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png index 47113e66d0..28e4e403fe 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1228309dd9c2dbaa340f1b941ca9da17067c619a8645e870f20bf39db7c9ba25 -size 27560 +oid sha256:2b8741879622a799c9cae5ba7ecb0f83700cdfca52dd9e6b281bfa0cc31267b3 +size 26817 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png index 12791633f9..2f7d54a7ac 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5b095c101503364437c57050c56fbcc56e8187a697921364eee4ae0807ad684e -size 38449 +oid sha256:61958e2bf98bcc380bca8622d53ea8d46ec466de6e8da134a9b01ea1605eca6c +size 38040 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png index edfa967da9..61aba383d1 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:128e6931b4ac3fbc02138fba8a67e22f60e722acddd8db26b1b031102bcbb198 -size 28060 +oid sha256:3e8275f65773690627383ef7f030f270c7f93639af5dff40ca46ee0c2d5e0316 +size 27628 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png index efb26f07c5..672f329d0d 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc9e3439b97efbd490030a7fdae43bccd60193b18c658f4ced99959550fc77bd -size 29481 +oid sha256:3efe6d5c4b5f02679eddf9be90af0ee0648a576a4488c021d9d7601aac3c71ab +size 29060 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png index 01f0712a7a..5d238d5c65 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ca99f565a56588d126e357df4417469e39ff196d21d41cdbff05166b8356da1 -size 21419 +oid sha256:17f591ce8aa0dc3c79dd450dc58b84194625f1eee1b8fb3d5dbd67b3b1e07966 +size 21035 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png index 2b260ff9f6..ba560e522f 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3b21d14f077ebcaa11ac2dca31fb08f9dc21f26a4847c6d1c623f0ec953cdc2 -size 45806 +oid sha256:7fff1e6cc2fe7ae2fe3dc81ee1f13f096245c238f3ca946ba4a353e693d0ecb8 +size 45468 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png index a584834ca9..893d7a086f 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bff3f28233c7b1be7c3524f06258dfcf27dffa4251279beb2bacb883c3c86c41 -size 28576 +oid sha256:e335a7132330e2c5dfb3f4cc015e25fdf67af2030474b347df2e0cca343b1c74 +size 27763 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png index bd510c21a9..7a2abd7f42 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f3ff8d40a465f3d73143de0d66566c0129a794cdba9556bb54423b2110375c8 -size 39033 +oid sha256:645d02f8d4503edfc2e5fb756050ed1ddb8a692d715d06b84b232e744379d613 +size 38820 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png index bc7f862d77..3b526c2fc1 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a7aab1f7cc5a26672666fab13a36fd7bb47d524b9ffa172bac322c1ad1c3b40 -size 28583 +oid sha256:4df58e4d7f0baeb0bfd0225302ed8e69eba1edc0ef37ae6cb8b86ffdd057b924 +size 28414 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png index 7cd952fef4..57bed01c00 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4743cbd8f565d114a74024455bddd999df95fba4c0ca346b32203cf6fb6f7550 -size 30203 +oid sha256:1a24be625e8a7d6eeb46f0066247bc22bd367b0e035802b54a663478392f4289 +size 29980 diff --git a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png index 9cbde40654..4537f0ff7f 100644 --- a/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png +++ b/screenshots/de/features.preferences.impl.root_PreferencesRootViewLight_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4a7e61a79e28968dfe2f57b75b88125471fecccdf4af670c7f2ca238019fc31c -size 21527 +oid sha256:f7a69722f7e5f6373a266116e7d97bef5e620b136deb2cea30409c41ec8d4180 +size 21310 diff --git a/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png b/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png index 29240c9037..6fe8d49af7 100644 --- a/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png +++ b/screenshots/de/features.rageshake.api.crash_CrashDetectionView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5d34090b6d2a05946f81c205b40dba420f49c19063b8f4bf2d0f55afe31886e7 -size 24441 +oid sha256:225e3ea78d7f1bf3bb9c2c56c128bdb6994b22df3f7c010837ef37bbcdc34997 +size 25170 diff --git a/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png b/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png index 39aa8e9965..c78691eca9 100644 --- a/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png +++ b/screenshots/de/features.rageshake.api.detection_RageshakeDialogContent_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2e6807ba4b85c71cca8aebaf34a22c836c6d53ebf8caaa42790594d3066956c -size 27850 +oid sha256:7546c33148ccc5d46e112c2488c6aecce925a9a0d729cc9c029c9dac2578e2a7 +size 28753 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png index 759f942a33..c39909cf49 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:088e737cec6fb5fbd624a16dbbcca45a8815441b93ef4d949acbaea9d9c52c3c -size 49472 +oid sha256:10355aa4b00cbaa5ccded1d03d23db71907f9943ebd40dfec50545c046991b61 +size 49461 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png index 10ad61fad0..7e18f43981 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f2f53b1fbc09307314ad92c688ef26490520de7380d27cab1ca67aca6e34a655 -size 47718 +oid sha256:7a2132a405f40d577a61420b4ad2d7bb9f55f67b5fe1b07b4ddb0daff10b8b89 +size 47704 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png index e95dd4de1d..4cd5290a7c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bab8c4a37f2d9fbd4b29cdd729db9a84216fcfae3023facbfb979ecdf4645b6 -size 46428 +oid sha256:e3003b423f3fa7504581ecf60cfbb82452eb17267bbc44f3b9439642da0ff096 +size 46416 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png index 32193ce5f1..0086307ec6 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6a11d9f2402b756b61a5ab3bb766bf19404fb24b306f86634650b070554268b -size 48264 +oid sha256:5bca6f953108331e512e3b0bca6086be207c1b1d2835d1dc220673098f5e3a9d +size 48263 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png index a29bbd09cb..0a99e31a52 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b37442dd675bf8ce133b57484ec8dc11c695df69907ead762fa4b79c7c978663 -size 48172 +oid sha256:494b1135a849734bce082b30aaeb491aebdb95cd67e6150be7334b55fe9fc0eb +size 48159 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png index 0fd4f66fcc..110a14531d 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa879e0d1483b07c3127ed07da87b8aabcc38c51db6e158ff29039e3b1886745 -size 49071 +oid sha256:2e147c903449a6c5ba6fa5041f73217c29965c2b4c2a165a96d36aebd2e2691e +size 49059 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png index 6100b21322..469a77a49a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05db3b3e42f59515ffad1c522496ebff6092bd458297ca92eba25b321d8be0ca -size 49564 +oid sha256:5590f66df4e26885e4b4776de840a9b1e4877a579f34769fe652172d01f5e374 +size 49554 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png index 63eb0980b8..7235a7a8e9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5662df69d4f1c66bb47019096df83031b190d7bc8e0b354c06f09d7c25d3773f -size 48454 +oid sha256:bbcc418cc648fe137d32a0455af4c0235c5c9269c49826c28dcdb22e7997638e +size 48441 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png index 44c943a262..6389db0432 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81ac09d41d5f08d8f4714f070c3661e0628a0d28f32d58eb0a1460eacb1be8d0 -size 47752 +oid sha256:a8d7ee825e1e2cb28babc26bdd2de3747c99bff0b95f6c7e4d8a2b2dd9f9dd49 +size 47758 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png index cf0d675e49..89c1174fd0 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dadbbe0ad65da59d7599f782e3893375867821ba0b8309c61a94f530cd58965 -size 44846 +oid sha256:2e6f13ca775952d7a06d82c41519a5f480f156eabd015a2020e0a5cf9d435765 +size 44694 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png index 3b5b87ac98..456f8db66c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d8648c9c6297f2e8ec87b334e1e885555e921faa7d98dda70fffb902ebe2688 -size 44828 +oid sha256:c84a92f1c008dffb95cf4aa1337a35ba208d3702decf912e084937665079d947 +size 44674 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png index c418b7d0b4..2f9e2bc268 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc469282e83bb5e88a173fc8a4500f8260f37ffc8afb20449e1126aa50631693 -size 43177 +oid sha256:29f45a3272a173614152dd6e7b0d3dc08de6d3b1f86c9683b267e97db773fb19 +size 43163 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png index 8360619979..fb90141dde 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a0a8cafff67aa2fd2991ce4320ed412cfebed0208b2d1c4e8bc0f45e7977e6b -size 48534 +oid sha256:cc70b1f6c6152f0f57b4f8586d781938c12af8bc61b517a232b779739eea6c72 +size 48521 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png index d0a134673b..10f31671ce 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3e1625ee06b9ae0025bf798705c8919b405f9cd917d85056623618fe0223e736 -size 48450 +oid sha256:8e5d32aea59c328b24d0a56bede3110e5b4a1d90a9b5eeb9bffffd30de5a41b6 +size 48437 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png index 720c2eeae6..2a3f4a388a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0aaf88dcf5e06d6c409318447e154b9d0b33775ad3e3aa8d8e3fe2b85aedd816 -size 48017 +oid sha256:ddddf06d51977bcd997e3680d2fe3ff4f9d8102848980cf88b4d2ef08e37d5f9 +size 48004 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png index e95f8da31b..28f7d63b1a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae9087dda9b2c6e160aa14dbb45e8ab614f2c315158c5bfc48d5c67058ebb63c -size 42639 +oid sha256:b5ffb5c4bb36e659d6650acfc43c560d6c6cfc26f7b663e6de036c8d210c3c53 +size 42627 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png index ac8ea4aa9b..b945a5f082 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d1c6f0c3898e000774de48cd7590c44bc11c297163735f16cc2dccaaf23e538 -size 45428 +oid sha256:cd4f6d16dbb22cd3968e4fb3a1408ee6387bb3f7d81388b18e4b4d7cdc24a2b8 +size 45416 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png index aeb6c18836..291e381783 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff3ddf54027d1f77d8e1e1f5cc063f1c13fc2725447d7cb6475c2ebb6c84b529 -size 47002 +oid sha256:19e656cf990a24bb08da6b7205a5fc1d39c76bbec967781cf0ea2a55bf7d11ab +size 46989 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png index a600833dc2..8ad5518a4c 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c99f882e777e43d1689ffa80a5396583426d987725424c779eff019f96d1c1bb -size 44444 +oid sha256:df3eb3ec43a8219be6e5fb27ae316222bf049d73d897712e9e4981c7cd482f66 +size 44290 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png index a4d831a49c..2524ad82a5 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:35aab3535b161bb3b111a9a352f510b43a25f9c98a7e5648aa3a380cd8402063 -size 45969 +oid sha256:babe700b98176da34b30db8fcd367f13b26eb0b8216f8a486d0462dccdbe3068 +size 44782 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png index 9d4d6b35bf..d3fe3eeec7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d637a9ab06a5eb79bbee7d141be92563d1c6d4acbb301b61a8c02db53e89132 -size 49078 +oid sha256:e78510f867c14a8cc9e98d6bf36880136f36cdf08cf8940b9a5f54e327a1f115 +size 49064 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png index 0884641063..ae3e083f08 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f45315776c2e841043aabdef8b72a8cd4e485270ada198b28f92de8f55bc7ca -size 48392 +oid sha256:627f61625aadbd1801d38dec33a107c72d9c2bc10057ab85ed15207557fb8343 +size 48379 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png index 82093102db..e52d7bbc87 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetailsDark_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:401e526ee8c3e27e90d34a9cb86561789172a9b91b5b5a6f5955aa4b001dfb1a -size 47658 +oid sha256:d3da232ee647be1a9722a00d4884f6f559cddc83f642aa07c3cbc4fb35746028 +size 47649 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png index d7778998b9..a825b90d21 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0f7fd6001307e447476310fc91cfe2eab0bddd8d0bc137a9a35698320f30f706 -size 50559 +oid sha256:3b17db5e3de5f2a7cd8ab5adb998b9343993aeb4ca7e072287e0f60064638155 +size 50517 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png index 777eaaf717..1e506d9628 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_10_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:17c582d1666c5c7b6040b007a13f0c6367eccd07d2a35847e4751bf8e5de7ed6 -size 48691 +oid sha256:e9165fa335486aa0463e9ee43b9e7c581a1c9bcd81f605a193d217fac58bff01 +size 48642 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png index c59448b50d..15456d858a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_11_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:673f1524b9a0e8284600cdcc5536bdf98574424c31a8a35552a75cbdd404424d -size 47490 +oid sha256:66d934f6d2fb764fd8d856e19671a47eb96bf79d1904222f12ba2c04ff815472 +size 47449 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png index f0c70fc293..759eda79f1 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_12_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7aff67290ac05d786c65cdc2dabc4bc6dbf60a802d0b77ae8c8404fd05e1bb7 -size 49256 +oid sha256:f6dfedba8b70af6389b88143e0c1c59dc9dbacba06b985fb791f9d5ef6b76d65 +size 49222 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png index 4c43697ac5..b50b33e08a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_13_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec0e7d344810f5fa43b9bc05c41116501350e3daedabd33c97782082264369ab -size 49157 +oid sha256:114059cd1d74d7e67039fdab4f4a37306badb38b2811b7cb494fd47a3de7dd52 +size 49118 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png index f0d89fc365..09a418c30b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_14_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a012a170cbd17e1fe588c27e41e531baa12097830ed205ac5c9c51c5bd62e003 -size 50108 +oid sha256:319b86e201bbcf3efb4ca2cceef15e7bba83800202c110439b5bab58d94aaa9d +size 50069 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png index 865602ac62..9bb6b27c92 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_15_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4f734bad723be9fada8b38763321ea63778f0ebfd65567472432ac32634d7b67 -size 50695 +oid sha256:0ddeb573fd6c83a7b0d9e00947a1f1b87c27eda69796285c7b9a6cee487ccbb1 +size 50653 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png index 1a59d9ec17..8c769eb3c2 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_16_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7a3c70bad40927fcd45902da33a3fe12fa50057e278c6009b1ed5befe4512182 -size 49470 +oid sha256:9a092056f5ae3f2bf40db0e1727afd191bf19b2bffea9bbeaa9cd5822b2235af +size 49426 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png index 1c01af3450..b7e8d5e7da 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_17_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9e7f2edac607fcd372a991078a4d9d92e01e148ddebce2785174dbf877e14bf -size 49045 +oid sha256:f300dbb1b0868fa619edef30e43231b5c2cb777bee2af56a8f3dfe42253db318 +size 48999 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png index aa64291503..602a4de377 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_18_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:755919c37c18cac3fe595975847620ce4a0b836b01546fbbfd3cdd1693ad5435 -size 45945 +oid sha256:2b7f04ee27a8cdc0b9cde949d6167f013cbf2cbfcf591a54262ca697fd54ab57 +size 46011 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png index 1cb9dd897b..0bb73f7526 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_19_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:735d92a8a39f4ec22ab51830cc0a5877697d028a12ba4cec2c2cce0475cddea5 -size 45888 +oid sha256:1d39a3067e1df646444276e13c1709e5c0ab0b27bb313531bdedde43fa056d6c +size 45947 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png index 1d527ce0e6..286ac63579 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7c9e86d87f93e3e96ee25b6090b0f989baf173a189a3c2274dc2cdd06dd566e1 -size 44223 +oid sha256:62ec3e5198b9d783cc7dcff94c39dec2ddd7edabbcbf1e272418e5446ec6d854 +size 44182 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png index c6e83dd003..673cdd0c30 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_20_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ed0a0e971a25574d13b6bbc5e0137f8a3f2bb1909d6149d16e09199dce3c25a -size 49535 +oid sha256:60c1951da07af010cd27d8622dcef6f953d369df9143a6c09e479bd26ea3aea9 +size 49487 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png index dd2ebef37e..49483a49d7 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_21_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fd5dcb36fc1e9cb675d461850e88f80402d30e43c6f8709ab3274326ad4a42b5 -size 49454 +oid sha256:951b4ed6186db857355229f9518aab6e72d0e6089e750eb58f1d21c23af54a58 +size 49415 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png index 9c0a4282b1..e49a2edf1b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_22_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b24f32d9a8640b7d1ef5a2b77d6198d3dbfabcab7a9cf46af8a0b24e23655eeb -size 48999 +oid sha256:9036a65f211de57afb08e2a8a1edc679690286063855146616d1a9205f5e92ba +size 48963 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png index 24966de76f..037c1a51b9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e92a8647bc6be119cb6dd401267f3369ad0ffa61372efc21d8e1752350c37a54 -size 43617 +oid sha256:c42fc0297235872ed4a405cbf73dbe68646b4ba2f2d8b4ab2a2c759372aedff5 +size 43575 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png index 95c8bffb80..c7dd2f7b1a 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39e4eab91f3d07daff1437991ec74005e7c79eed3f9b4ff71c154d68bbce3e71 -size 46400 +oid sha256:36df2a8757b8fea88e4d03150b7c9f1349e4112b1c7172224818cf394eb8755f +size 46360 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png index 5c5bc77cb2..731d5599be 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ce073c24e1d2b0cfcc6fc64cc62042c5bb9260e7636441827fdc746964aefbe -size 48017 +oid sha256:73a5e4314e7d2cfffff54c1181aab1fb95227172758299c06754e97b59a58bba +size 47972 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png index 0a07cb8799..fb6a42fde4 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_5_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:19fa23046e80df108a9d9cabe2b34d713e12d74127b3c4a320b5770e286429ea -size 45506 +oid sha256:9dec4b40543155b80a9d1db51a97f269d6188c0ea84384abf37e7c32a953a4c3 +size 45565 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png index 71787b6f1f..6ce7d985b9 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_6_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb164e2c9796a1d12a0146b3fb67d29813be54d42b0628d17a323a525b866177 -size 47065 +oid sha256:2d575f4e716de7fc5e1d376a8225f69bcf5375ea8a1555baa8d27d0481b45d4b +size 46038 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png index a9ebd612f5..28cb1f210b 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_7_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d764589c800027ef6f34660324d980c6525475b0a65d7f1e7b4afa4f4f19aaa -size 50155 +oid sha256:8a4d42087d391ecc107d9f485e97499a9952f85c7555ac4428d36f4565c75dba +size 50112 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png index 9a167dc9b8..8c515e1bfe 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3784f50878f750bc04b45ca657ccb89d74343164ef7b0aa06fb43260f46ef72 -size 49429 +oid sha256:a5b97717f51c11b13b760cdb6922587db19d962f1f47c7c45bb39de2fc7880af +size 49374 diff --git a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png index b2f44c24d5..04877ee746 100644 --- a/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png +++ b/screenshots/de/features.roomdetails.impl_RoomDetails_9_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91302b37b756a39cae34160110d2f7bb3fd67129343cde63ae22b109861299c7 -size 48671 +oid sha256:29a2b72b3ab467665c819763eee041fe349d26d9d2b6b724677a071dfcb84450 +size 48626 diff --git a/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png b/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png index 34d3e5d494..e86f031a8e 100644 --- a/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png +++ b/screenshots/de/features.startchat.impl.components_SearchMultipleUsersResultItem_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:993191e7db24d10111a3b7c22c0e192e28e9a3e170edb57de14ec205de73cf15 -size 95383 +oid sha256:fa263cc9cfb7cc47dacfa4ea65a9f4e8660e1a17df61e357d5cf76928dd89100 +size 90714 diff --git a/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png b/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png index 8d1aac76c6..3eff580ee8 100644 --- a/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png +++ b/screenshots/de/features.startchat.impl.components_SearchSingleUserResultItem_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93b60fdeb5bd6fbf7f3ab3eca81f2109b02101bec9a8c812ceb02ac8d19840e2 -size 51866 +oid sha256:caa936c590efb400eec2e3d238bec4e48b81883371057f34badf0abb1644554c +size 49654 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png index 502b87bbdb..1230b616fd 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f7884a15f505913ba13dcd99320b1b9d26cbf1e8f15eb051e65d8fbedc1a828c -size 27673 +oid sha256:fa14bce431debf9d9a64c4a47bed9d89730fb21d480af186dc2ac53a9e52f1af +size 31785 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png index 33479d694d..14b7d796bc 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8cea006dcb900e70cc9f4be90b9144e340768e7d23d90932c99422eaf8ea96fb -size 21203 +oid sha256:0f4fe803d3318a31919099958d793ecb4f5eae7109596712de23c89e6c982ea4 +size 20145 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png index e4c6ad93ff..358883997e 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:41ddc90c4f22013037b7786f2b91e35dd2db7329d43f12cb72f8cd1474e89d3c -size 31725 +oid sha256:a99cb9da94e1ea3050ccb1e9c32380fde1b5e55ea806c4c2aa5f7bc8c5d0b0fd +size 30750 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png index 3e3fcc2526..fc81f7c584 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_3_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a17fadc85a373556a338cd4c9ceaf35432b1853e06641237e6d3f4bf7cd0979 -size 51495 +oid sha256:af238ae63b675069702e65b52c1e4b272294aa0a2c971a3394a67535ee89e45c +size 51165 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png index 75e7c2f592..3bbed27e43 100644 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png +++ b/screenshots/de/features.startchat.impl.root_StartChatView_Day_4_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:44855b0887ce9ccd5a0302c8d11ba6bf556badaefd33f897c5635d49cb44a99e -size 45071 +oid sha256:26cbf2c908b89e8cd2daa1a35cfd58dcea951e03a2ecc2334af7d8241d038254 +size 41339 diff --git a/screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png b/screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png deleted file mode 100644 index 1230b616fd..0000000000 --- a/screenshots/de/features.startchat.impl.root_StartChatView_Day_5_de.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fa14bce431debf9d9a64c4a47bed9d89730fb21d480af186dc2ac53a9e52f1af -size 31785 diff --git a/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png b/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png index ebf998ba32..5b11ec067d 100644 --- a/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png +++ b/screenshots/de/features.userprofile.shared_UserProfileView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aa5d7bb68d549eab01750a043f0c844cf9ff2609e813fa6be5170f7e47da04f4 -size 36872 +oid sha256:35ac4bfa2e7bffba17448459c52098400f421fc3af55a7de16c24f3f293d0d42 +size 36464 diff --git a/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png b/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png index 88e163b840..5fc8b4a8fe 100644 --- a/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CheckableUnresolvedUserRow_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4d6fb36f1340276b3f525505e8a51245f63a1fbe8637ad33c9c3c2ef793679d -size 114204 +oid sha256:81e2d991659061d40047373c3b3aedff5a4bc2b42c2b1355448b73784891b2f5 +size 109822 diff --git a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png index 74fca61a42..6b49ae7f1a 100644 --- a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a9da4a0d12b26e2bf2bc3c6a0b032d462ccce782ee6ed5a62c7c32a7c2d4e0a2 -size 28400 +oid sha256:4484ff8dbba915c439270cbebab45c503d94dc82c7641a674153d88aa2aa3143 +size 28017 diff --git a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png index 6e9497454b..752973ddb4 100644 --- a/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png +++ b/screenshots/de/libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d365fb5ebb274cdf830763e8354e5fb532929f590f9ae93259c823fa66a64a5 -size 39239 +oid sha256:402ca214ecc34d4a5a5faf7583a879ab26e6c64b86904034dfa050a27a7b7a2d +size 38789 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png index 169e0d2b10..f89e8cf1c5 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_2_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:622e92307a1aae1a9feb420709f74d9cef063cdfd8e9f562e65655cb54ee804f -size 9991 +oid sha256:f02b4fe30d6ab57d618c925d3a110b5ca8f299717032b1380d91437acda62b7b +size 11633 diff --git a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png index e2acbcc89c..6aee76799c 100644 --- a/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png +++ b/screenshots/de/libraries.matrix.ui.components_SpaceRoomItemView_Day_8_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ad1db5f211ed3df04d31e973297a82685168834ee6b629ce10c3b9e82c226c9 -size 10512 +oid sha256:1dde928940515398c089e258787afca156fd1dceb9b80559c339e94e97864f12 +size 12052 diff --git a/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png b/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png index 250826b00d..25ad5c2356 100644 --- a/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png +++ b/screenshots/de/libraries.matrix.ui.components_UnresolvedUserRow_de.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7179346d56f1c4772169e344f1e5f01b42a5cbb86093dc6e14728f970f5fc6b -size 72739 +oid sha256:76955fb8324747c81687727bbced594f00d2c2610d91474123ecd6ced14394a4 +size 70297 diff --git a/screenshots/html/data.js b/screenshots/html/data.js index 2cd7772aff..eea6b4b636 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,99 +1,100 @@ // Generated file, do not edit export const screenshots = [ ["en","en-dark","de",], -["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_ATimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components.event_ATimelineItemEventRow_Night_0_en",0,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20581,], ["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_0_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_0_en",0,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20573,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20573,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20573,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20573,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20581,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20581,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20581,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20581,], ["features.login.impl.accountprovider_AccountProviderView_Day_0_en","features.login.impl.accountprovider_AccountProviderView_Night_0_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_1_en","features.login.impl.accountprovider_AccountProviderView_Night_1_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_2_en","features.login.impl.accountprovider_AccountProviderView_Night_2_en",0,], ["features.login.impl.accountprovider_AccountProviderView_Day_3_en","features.login.impl.accountprovider_AccountProviderView_Night_3_en",0,], -["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20573,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20573,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20581,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20581,], ["features.messages.impl.actionlist_ActionListViewContent_Day_0_en","features.messages.impl.actionlist_ActionListViewContent_Night_0_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20581,], ["features.messages.impl.actionlist_ActionListViewContent_Day_1_en","features.messages.impl.actionlist_ActionListViewContent_Night_1_en",0,], -["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20573,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20573,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20573,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20573,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20573,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20573,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20581,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20581,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20581,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20581,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20581,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20581,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20573,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20573,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20573,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20573,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20573,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20581,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20581,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20581,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20581,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20581,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20573,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20573,], -["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20573,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20573,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",20581,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",20581,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",20581,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20581,], ["libraries.designsystem.components.async_AsyncActionView_Day_0_en","libraries.designsystem.components.async_AsyncActionView_Night_0_en",0,], -["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20573,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20581,], ["libraries.designsystem.components.async_AsyncActionView_Day_2_en","libraries.designsystem.components.async_AsyncActionView_Night_2_en",0,], -["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20573,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20581,], ["libraries.designsystem.components.async_AsyncActionView_Day_4_en","libraries.designsystem.components.async_AsyncActionView_Night_4_en",0,], -["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20573,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20581,], ["libraries.designsystem.components.async_AsyncIndicatorFailure_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorFailure_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncIndicatorLoading_Day_0_en","libraries.designsystem.components.async_AsyncIndicatorLoading_Night_0_en",0,], ["libraries.designsystem.components.async_AsyncLoading_Day_0_en","libraries.designsystem.components.async_AsyncLoading_Night_0_en",0,], -["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20573,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20581,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_0_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_0_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_1_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_1_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_2_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_2_en",0,], @@ -103,19 +104,19 @@ export const screenshots = [ ["libraries.matrix.ui.components_AttachmentThumbnail_Day_6_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_6_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_7_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_7_en",0,], ["libraries.matrix.ui.components_AttachmentThumbnail_Day_8_en","libraries.matrix.ui.components_AttachmentThumbnail_Night_8_en",0,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20573,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20573,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20581,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20581,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_1_en",0,], ["libraries.mediaviewer.impl.gallery.ui_AudioItemView_Day_2_en","libraries.mediaviewer.impl.gallery.ui_AudioItemView_Night_2_en",0,], -["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20573,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20581,], ["libraries.designsystem.components.avatar.internal_AvatarCluster_Avatars_en","",0,], ["libraries.matrix.ui.components_AvatarPickerSizes_Day_0_en","libraries.matrix.ui.components_AvatarPickerSizes_Night_0_en",0,], ["libraries.matrix.ui.components_AvatarPickerViewRtl_Day_0_en","libraries.matrix.ui.components_AvatarPickerViewRtl_Night_0_en",0,], @@ -145,22 +146,22 @@ export const screenshots = [ ["libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradientDisabled_Night_0_en",0,], ["libraries.designsystem.modifiers_BackgroundVerticalGradient_Day_0_en","libraries.designsystem.modifiers_BackgroundVerticalGradient_Night_0_en",0,], ["libraries.designsystem.components_Badge_Day_0_en","libraries.designsystem.components_Badge_Night_0_en",0,], -["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20573,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20581,], ["libraries.designsystem.atomic.atoms_BetaLabel_Day_0_en","libraries.designsystem.atomic.atoms_BetaLabel_Night_0_en",0,], ["libraries.designsystem.components_BigIcon_Day_0_en","libraries.designsystem.components_BigIcon_Night_0_en",0,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20573,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20573,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20581,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20581,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20573,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20573,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20581,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20581,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -171,141 +172,141 @@ export const screenshots = [ ["features.messages.impl.timeline.components_CallMenuItem_Day_0_en","features.messages.impl.timeline.components_CallMenuItem_Night_0_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_1_en","features.messages.impl.timeline.components_CallMenuItem_Night_1_en",0,], ["features.messages.impl.timeline.components_CallMenuItem_Day_2_en","features.messages.impl.timeline.components_CallMenuItem_Night_2_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20573,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20573,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20581,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20581,], ["features.messages.impl.timeline.components_CallMenuItem_Day_5_en","features.messages.impl.timeline.components_CallMenuItem_Night_5_en",0,], -["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20573,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20581,], ["features.messages.impl.timeline.components_CallMenuItem_Day_7_en","features.messages.impl.timeline.components_CallMenuItem_Night_7_en",0,], ["features.call.impl.ui_CallScreenView_Day_0_en","features.call.impl.ui_CallScreenView_Night_0_en",0,], -["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20573,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20573,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20573,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20573,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20573,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20581,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20581,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20581,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20581,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20581,], ["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_5_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_5_en",0,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20573,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20573,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20573,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20581,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20581,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20581,], ["features.login.impl.changeserver_ChangeServerView_Day_0_en","features.login.impl.changeserver_ChangeServerView_Night_0_en",0,], -["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20573,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20573,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20581,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20581,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20573,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20581,], ["libraries.designsystem.theme.components_Checkboxes_Toggles_en","",0,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20573,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20573,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20573,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20581,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20581,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20581,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], -["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20577,], +["features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Day_0_en","features.linknewdevice.impl.screens.confirmation_CodeConfirmationView_Night_0_en",20581,], ["libraries.designsystem.theme_ColorAliases_Day_0_en","libraries.designsystem.theme_ColorAliases_Night_0_en",0,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20573,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20573,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20573,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20581,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20581,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20581,], ["libraries.textcomposer_ComposerModeView_Day_1_en","libraries.textcomposer_ComposerModeView_Night_1_en",0,], ["libraries.textcomposer_ComposerModeView_Day_2_en","libraries.textcomposer_ComposerModeView_Night_2_en",0,], ["libraries.textcomposer_ComposerModeView_Day_3_en","libraries.textcomposer_ComposerModeView_Night_3_en",0,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20573,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20573,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20573,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20573,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20573,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20581,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20581,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20581,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20581,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20581,], ["libraries.designsystem.components.dialogs_ConfirmationDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ConfirmationDialog_Day_0_en","libraries.designsystem.components.dialogs_ConfirmationDialog_Night_0_en",0,], ["features.networkmonitor.api.ui_ConnectivityIndicator_Day_0_en","features.networkmonitor.api.ui_ConnectivityIndicator_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_CounterAtom_Day_0_en","libraries.designsystem.atomic.atoms_CounterAtom_Night_0_en",0,], -["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20573,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20573,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20573,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20573,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20573,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20573,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20573,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20573,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20573,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20573,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20573,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20573,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20573,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20581,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20581,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20581,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20581,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20581,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20581,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20581,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20581,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20581,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20581,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20581,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20581,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20581,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_DateItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_DateItemView_Night_1_en",0,], -["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20573,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20573,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20573,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20581,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20581,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_0_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_0_en",0,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20573,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20573,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20573,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20581,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20581,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20581,], ["features.logout.impl.direct_DefaultDirectLogoutView_Day_4_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_4_en",0,], -["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20573,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20581,], ["features.licenses.impl.details_DependenciesDetailsView_Day_0_en","features.licenses.impl.details_DependenciesDetailsView_Night_0_en",0,], -["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20573,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20573,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20573,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20573,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20573,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20573,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20573,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20581,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20581,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20581,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20581,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20581,], ["libraries.designsystem.theme.components_DialogWithDestructiveButton_Dialog_with_destructive_button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithOnlyMessageAndOkButton_Dialog_with_only_message_and_ok_button_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithThirdButton_Dialog_with_third_button_Dialogs_en","",0,], @@ -314,26 +315,24 @@ export const screenshots = [ ["libraries.designsystem.theme.components_DialogWithVeryLongTitleAndIcon_Dialog_with_a_very_long_title_and_icon_Dialogs_en","",0,], ["libraries.designsystem.theme.components_DialogWithVeryLongTitle_Dialog_with_a_very_long_title_Dialogs_en","",0,], ["features.messages.impl.messagecomposer_DisabledComposerView_Day_0_en","features.messages.impl.messagecomposer_DisabledComposerView_Night_0_en",0,], -["libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en","",0,], -["libraries.designsystem.components.avatar_DmAvatars_Avatars_en","",0,], ["libraries.designsystem.text_DpScale_0_75f__en","",0,], ["libraries.designsystem.text_DpScale_1_0f__en","",0,], ["libraries.designsystem.text_DpScale_1_5f__en","",0,], ["libraries.designsystem.theme.components_DropdownMenuItem_Menus_en","",0,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20573,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20573,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20573,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20573,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20581,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20581,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20581,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",20581,], ["libraries.matrix.ui.components_EditableOrgAvatarRtl_Day_0_en","libraries.matrix.ui.components_EditableOrgAvatarRtl_Night_0_en",0,], ["libraries.matrix.ui.components_EditableOrgAvatar_Day_0_en","libraries.matrix.ui.components_EditableOrgAvatar_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomLargeNoBlurShadow_Night_0_en",0,], @@ -341,29 +340,29 @@ export const screenshots = [ ["libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMediumNoBlurShadow_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Day_0_en","libraries.designsystem.atomic.atoms_ElementLogoAtomMedium_Night_0_en",0,], ["features.messages.impl.timeline.components.customreaction_EmojiItem_Day_0_en","features.messages.impl.timeline.components.customreaction_EmojiItem_Night_0_en",0,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20573,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20573,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20581,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20581,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_2_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_2_en",0,], ["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_3_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_3_en",0,], ["libraries.ui.common.nodes_EmptyView_Day_0_en","libraries.ui.common.nodes_EmptyView_Night_0_en",0,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20573,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20573,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20573,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20573,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20577,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20581,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20581,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20581,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_8_en","features.linknewdevice.impl.screens.error_ErrorView_Night_8_en",20581,], ["features.messages.impl.timeline.debug_EventDebugInfoView_Day_0_en","features.messages.impl.timeline.debug_EventDebugInfoView_Night_0_en",0,], ["libraries.designsystem.components_ExpandableBottomSheetLayout_en","",0,], ["libraries.featureflag.ui_FeatureListView_Day_0_en","libraries.featureflag.ui_FeatureListView_Night_0_en",0,], @@ -383,49 +382,49 @@ export const screenshots = [ ["features.messages.impl.timeline.components_FloatingDateBadge_Day_0_en","features.messages.impl.timeline.components_FloatingDateBadge_Night_0_en",0,], ["libraries.designsystem.atomic.pages_FlowStepPage_Day_0_en","libraries.designsystem.atomic.pages_FlowStepPage_Night_0_en",0,], ["features.messages.impl.timeline.focus_FocusRequestStateView_Day_0_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_0_en",0,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20573,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20573,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20573,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20581,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20581,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20581,], ["features.messages.impl.timeline.components_FocusedEvent_Day_0_en","features.messages.impl.timeline.components_FocusedEvent_Night_0_en",0,], ["libraries.textcomposer.components_FormattingOption_Day_0_en","libraries.textcomposer.components_FormattingOption_Night_0_en",0,], ["features.forward.impl_ForwardMessagesView_Day_0_en","features.forward.impl_ForwardMessagesView_Night_0_en",0,], ["features.forward.impl_ForwardMessagesView_Day_1_en","features.forward.impl_ForwardMessagesView_Night_1_en",0,], ["features.forward.impl_ForwardMessagesView_Day_2_en","features.forward.impl_ForwardMessagesView_Night_2_en",0,], -["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20573,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20573,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20581,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20581,], ["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_0_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_0_en",0,], -["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20573,], +["features.announcement.impl.fullscreen_FullscreenAnnouncementView_Day_1_en","features.announcement.impl.fullscreen_FullscreenAnnouncementView_Night_1_en",20581,], ["libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButtonCircleShape_Night_0_en",0,], ["libraries.designsystem.components.button_GradientFloatingActionButton_Day_0_en","libraries.designsystem.components.button_GradientFloatingActionButton_Night_0_en",0,], ["features.messages.impl.timeline.components.group_GroupHeaderView_Day_0_en","features.messages.impl.timeline.components.group_GroupHeaderView_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPageScrollable_Night_0_en",0,], ["libraries.designsystem.atomic.pages_HeaderFooterPage_Day_0_en","libraries.designsystem.atomic.pages_HeaderFooterPage_Night_0_en",0,], -["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20573,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20573,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20573,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20573,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20573,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20581,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20581,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20581,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20581,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20581,], ["features.home.impl.components_HomeTopBarSpaces_Day_0_en","features.home.impl.components_HomeTopBarSpaces_Night_0_en",0,], -["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20573,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20573,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20581,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20581,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20573,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20573,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20581,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20581,], ["features.home.impl_HomeView_Day_11_en","features.home.impl_HomeView_Night_11_en",0,], ["features.home.impl_HomeView_Day_12_en","features.home.impl_HomeView_Night_12_en",0,], -["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20573,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20573,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20573,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20573,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20573,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20573,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20573,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20573,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20573,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20573,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20573,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20573,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20573,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20581,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20581,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20581,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20581,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20581,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20581,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20581,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20581,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20581,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20581,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20581,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20581,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20581,], ["libraries.designsystem.theme.components_HorizontalDivider_Dividers_en","",0,], ["libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Day_0_en","libraries.designsystem.theme.components_HorizontalFloatingToolbarNoFab_Night_0_en",0,], ["libraries.designsystem.theme.components_HorizontalFloatingToolbar_Day_0_en","libraries.designsystem.theme.components_HorizontalFloatingToolbar_Night_0_en",0,], @@ -440,8 +439,8 @@ export const screenshots = [ ["appicon.element_Icon_en","",0,], ["libraries.designsystem.icons_IconsOther_Day_0_en","libraries.designsystem.icons_IconsOther_Night_0_en",0,], ["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_0_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_0_en",0,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20573,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20573,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20581,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20581,], ["libraries.mediaviewer.impl.gallery.ui_ImageItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_ImageItemView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_0_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_0_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_10_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_10_en",0,], @@ -449,119 +448,119 @@ export const screenshots = [ ["libraries.matrix.ui.messages.reply_InReplyToView_Day_1_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_1_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_2_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_2_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_3_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_3_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20573,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20581,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_5_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_5_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_6_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_6_en",0,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_7_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_7_en",0,], -["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20573,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20581,], ["libraries.matrix.ui.messages.reply_InReplyToView_Day_9_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_9_en",0,], -["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20573,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20573,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20581,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20581,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20573,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20573,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20581,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20581,], ["libraries.designsystem.atomic.molecules_InfoListItemMolecule_Day_0_en","libraries.designsystem.atomic.molecules_InfoListItemMolecule_Night_0_en",0,], ["libraries.designsystem.atomic.organisms_InfoListOrganism_Day_0_en","libraries.designsystem.atomic.organisms_InfoListOrganism_Night_0_en",0,], ["libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Day_0_en","libraries.matrix.ui.media_InitialsAvatarBitmapGenerator_Night_0_en",0,], -["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20573,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",20581,], ["features.invitepeople.impl_InvitePeopleView_Day_11_en","features.invitepeople.impl_InvitePeopleView_Night_11_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20581,], ["features.invitepeople.impl_InvitePeopleView_Day_2_en","features.invitepeople.impl_InvitePeopleView_Night_2_en",0,], ["features.invitepeople.impl_InvitePeopleView_Day_3_en","features.invitepeople.impl_InvitePeopleView_Night_3_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20573,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20581,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20581,], ["features.invitepeople.impl_InvitePeopleView_Day_8_en","features.invitepeople.impl_InvitePeopleView_Night_8_en",0,], -["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20573,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20573,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20573,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20581,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20581,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20581,], ["features.joinroom.impl_JoinRoomView_Day_0_en","features.joinroom.impl_JoinRoomView_Night_0_en",0,], -["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20573,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20573,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20573,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20573,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20581,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20581,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20581,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20581,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20573,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20573,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20581,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20581,], ["features.leaveroom.impl_LeaveRoomView_Day_0_en","features.leaveroom.impl_LeaveRoomView_Night_0_en",0,], -["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20573,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20573,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20573,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20581,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20581,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20581,], ["libraries.designsystem.background_LightGradientBackground_Day_0_en","libraries.designsystem.background_LightGradientBackground_Night_0_en",0,], ["libraries.designsystem.theme.components_LinearProgressIndicator_Progress_Indicators_en","",0,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20573,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20573,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20581,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20581,], ["features.messages.impl.link_LinkView_Day_0_en","features.messages.impl.link_LinkView_Night_0_en",0,], -["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20573,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20581,], ["libraries.designsystem.components.dialogs_ListDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_ListDialog_Day_0_en","libraries.designsystem.components.dialogs_ListDialog_Night_0_en",0,], ["libraries.designsystem.theme.components_ListItemPrimaryActionWithIcon_List_item_-_Primary_action_&_Icon_List_items_en","",0,], @@ -616,45 +615,45 @@ export const screenshots = [ ["libraries.designsystem.theme.components_ListSupportingTextSmallPadding_List_supporting_text_-_small_padding_List_sections_en","",0,], ["libraries.textcomposer.components_LiveWaveformView_Day_0_en","libraries.textcomposer.components_LiveWaveformView_Night_0_en",0,], ["appnav.room.joined_LoadingRoomNodeView_Day_0_en","appnav.room.joined_LoadingRoomNodeView_Night_0_en",0,], -["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20573,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20581,], ["libraries.designsystem.components_LocationPin_Day_0_en","libraries.designsystem.components_LocationPin_Night_0_en",0,], ["features.location.impl.common.ui_LocationShareRow_Day_0_en","features.location.impl.common.ui_LocationShareRow_Night_0_en",0,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20573,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20573,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20573,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20581,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20581,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20581,], ["appnav.loggedin_LoggedInView_Day_0_en","appnav.loggedin_LoggedInView_Night_0_en",0,], -["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20573,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20573,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20573,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20573,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20573,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20573,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20573,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20573,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20573,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20573,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20573,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20573,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20573,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20573,], -["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20573,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20573,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20573,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20573,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20573,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20573,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20573,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20573,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20573,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20573,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20573,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20573,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20573,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20581,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20581,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20581,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20581,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20581,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20581,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20581,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20581,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20581,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20581,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20581,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20581,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20581,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",20581,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",20581,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20581,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20581,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20581,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20581,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20581,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20581,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20581,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20581,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20581,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20581,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20581,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20581,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20573,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20573,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20573,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20573,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20581,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20581,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20581,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20581,], ["libraries.textcomposer.components.markdown_MarkdownTextInput_Day_0_en","libraries.textcomposer.components.markdown_MarkdownTextInput_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomInfo_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNegative_Night_0_en",0,], @@ -667,26 +666,26 @@ export const screenshots = [ ["libraries.matrix.ui.components_MatrixUserRow_Day_1_en","libraries.matrix.ui.components_MatrixUserRow_Night_1_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_0_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.audio_MediaAudioView_Day_1_en","libraries.mediaviewer.impl.local.audio_MediaAudioView_Night_1_en",0,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20573,], -["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20573,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20573,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20581,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_1_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_1_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_1_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_2_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_2_en",20581,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_3_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_3_en",20581,], ["libraries.mediaviewer.impl.local.file_MediaFileView_Day_0_en","libraries.mediaviewer.impl.local.file_MediaFileView_Night_0_en",0,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20573,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20573,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20581,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20581,], ["libraries.mediaviewer.impl.local.image_MediaImageView_Day_0_en","libraries.mediaviewer.impl.local.image_MediaImageView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_0_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_0_en",0,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_1_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_1_en",0,], @@ -694,15 +693,20 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.video_MediaVideoView_Day_0_en","libraries.mediaviewer.impl.local.video_MediaVideoView_Night_0_en",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20573,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_11_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], @@ -712,15 +716,20 @@ export const screenshots = [ ["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_9_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_0_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_10_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20573,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20581,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_15_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_16_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_17_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_18_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_19_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20573,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_20_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_21_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_22_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20581,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -734,7 +743,7 @@ export const screenshots = [ ["libraries.textcomposer.mentions_MentionSpanTheme_Day_0_en","libraries.textcomposer.mentions_MentionSpanTheme_Night_0_en",0,], ["libraries.designsystem.theme.components.previews_Menu_Menus_en","",0,], ["features.messages.impl.messagecomposer_MessageComposerViewVoice_Day_0_en","features.messages.impl.messagecomposer_MessageComposerViewVoice_Night_0_en",0,], -["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20573,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20581,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_0_en","features.messages.impl.timeline.components_MessageEventBubble_Night_0_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_1_en","features.messages.impl.timeline.components_MessageEventBubble_Night_1_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_2_en","features.messages.impl.timeline.components_MessageEventBubble_Night_2_en",0,], @@ -743,7 +752,7 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessageEventBubble_Day_5_en","features.messages.impl.timeline.components_MessageEventBubble_Night_5_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_6_en","features.messages.impl.timeline.components_MessageEventBubble_Night_6_en",0,], ["features.messages.impl.timeline.components_MessageEventBubble_Day_7_en","features.messages.impl.timeline.components_MessageEventBubble_Night_7_en",0,], -["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20573,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20581,], ["features.messages.impl.timeline.components_MessageStateEventContainer_Day_0_en","features.messages.impl.timeline.components_MessageStateEventContainer_Night_0_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButtonAdd_Day_0_en","features.messages.impl.timeline.components_MessagesReactionButtonAdd_Night_0_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButtonExtra_Day_0_en","features.messages.impl.timeline.components_MessagesReactionButtonExtra_Night_0_en",0,], @@ -752,23 +761,23 @@ export const screenshots = [ ["features.messages.impl.timeline.components_MessagesReactionButton_Day_2_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_2_en",0,], ["features.messages.impl.timeline.components_MessagesReactionButton_Day_3_en","features.messages.impl.timeline.components_MessagesReactionButton_Night_3_en",0,], ["features.messages.impl_MessagesViewA11y_en","",0,], -["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20573,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20573,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20573,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20573,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20573,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20573,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20573,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20573,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20573,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20573,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20573,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20573,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20573,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20573,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20573,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20581,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20581,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20581,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20581,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20581,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20581,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20581,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20581,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20581,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20581,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20581,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20581,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20581,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20581,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20581,], ["features.migration.impl_MigrationView_Day_0_en","features.migration.impl_MigrationView_Night_0_en",0,], -["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20573,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20581,], ["features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en","features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en",0,], ["libraries.designsystem.theme.components_ModalBottomSheetDark_Bottom_Sheets_en","",0,], ["libraries.designsystem.theme.components_ModalBottomSheetLight_Bottom_Sheets_en","",0,], @@ -779,113 +788,117 @@ export const screenshots = [ ["libraries.designsystem.components.list_MutipleSelectionListItemSelected_Multiple_selection_List_item_-_selection_in_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_MutipleSelectionListItem_Multiple_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_NavigationBar_App_Bars_en","",0,], -["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20573,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20573,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20573,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20581,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20581,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20581,], ["features.linknewdevice.impl.screens.number.component_NumberTextField_Day_0_en","features.linknewdevice.impl.screens.number.component_NumberTextField_Night_0_en",0,], ["libraries.designsystem.atomic.pages_OnBoardingPage_Day_0_en","libraries.designsystem.atomic.pages_OnBoardingPage_Night_0_en",0,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20573,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20573,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20581,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",20581,], ["libraries.designsystem.background_OnboardingBackground_Day_0_en","libraries.designsystem.background_OnboardingBackground_Night_0_en",0,], -["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20573,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20581,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_12_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_12_en",0,], ["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_13_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_13_en",0,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20573,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20573,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20581,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20581,], ["libraries.designsystem.theme.components_OutlinedButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_OutlinedButtonSmall_Buttons_en","",0,], -["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20573,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20573,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20573,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20573,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20573,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20573,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20581,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20581,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20581,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20581,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20581,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20581,], ["features.lockscreen.impl.components_PinEntryTextField_Day_0_en","features.lockscreen.impl.components_PinEntryTextField_Night_0_en",0,], ["features.lockscreen.impl.unlock.keypad_PinKeypad_Day_0_en","features.lockscreen.impl.unlock.keypad_PinKeypad_Night_0_en",0,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20573,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20573,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20581,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_8_en","features.lockscreen.impl.unlock_PinUnlockView_Night_8_en",20584,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_9_en","features.lockscreen.impl.unlock_PinUnlockView_Night_9_en",20584,], ["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_0_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_0_en",0,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20573,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20573,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20573,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20581,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20581,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20581,], ["libraries.designsystem.atomic.atoms_PlaceholderAtom_Day_0_en","libraries.designsystem.atomic.atoms_PlaceholderAtom_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_PlaybackSpeedButton_Day_0_en","libraries.designsystem.atomic.atoms_PlaybackSpeedButton_Night_0_en",0,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20573,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20573,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20581,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20581,], ["features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedNotSelected_Night_0_en",0,], ["features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewUndisclosedSelected_Night_0_en",0,], -["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20573,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20573,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20573,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20581,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20581,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20581,], ["features.poll.api.pollcontent_PollTitleView_Day_0_en","features.poll.api.pollcontent_PollTitleView_Night_0_en",0,], ["libraries.designsystem.components.preferences_PreferenceCategory_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceCheckbox_Preferences_en","",0,], @@ -899,225 +912,225 @@ export const screenshots = [ ["libraries.designsystem.components.preferences_PreferenceRow_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSlide_Preferences_en","",0,], ["libraries.designsystem.components.preferences_PreferenceSwitch_Preferences_en","",0,], -["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20573,], -["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20573,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",20581,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",20581,], ["features.messages.impl.timeline.components.event_ProgressButton_Day_0_en","features.messages.impl.timeline.components.event_ProgressButton_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20573,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20581,], ["libraries.designsystem.components_ProgressDialogWithTextAndContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithTextAndContent_Night_0_en",0,], -["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20573,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20573,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20573,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20573,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20573,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20573,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20573,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20581,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20581,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20581,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20581,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20581,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20581,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20581,], ["libraries.qrcode_QrCodeView_en","",0,], ["libraries.designsystem.theme.components_RadioButton_Toggles_en","",0,], -["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20573,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20573,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20581,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20581,], ["features.rageshake.api.preferences_RageshakePreferencesView_Day_1_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_1_en",0,], ["features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Day_0_en","features.messages.impl.timeline.components.reactionsummary_ReactionSummaryViewContent_Night_0_en",0,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20573,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20573,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20573,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20581,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20581,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20581,], ["libraries.designsystem.atomic.atoms_RedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_RedIndicatorAtom_Night_0_en",0,], ["features.messages.impl.timeline.components_ReplySwipeIndicator_Day_0_en","features.messages.impl.timeline.components_ReplySwipeIndicator_Night_0_en",0,], -["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20573,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20573,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20573,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20573,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20573,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20573,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20581,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20581,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20581,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20581,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20581,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20581,], ["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_0_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_0_en",0,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20573,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20573,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20573,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20573,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20573,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20581,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20581,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20581,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20581,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20581,], ["libraries.matrix.ui.room.address_RoomAddressField_Day_0_en","libraries.matrix.ui.room.address_RoomAddressField_Night_0_en",0,], ["features.roomaliasresolver.impl_RoomAliasResolverView_Day_0_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_0_en",0,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20573,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20573,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20581,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20581,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20573,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20573,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20573,], -["features.roomdetails.impl_RoomDetails_0_en","",20573,], -["features.roomdetails.impl_RoomDetails_10_en","",20573,], -["features.roomdetails.impl_RoomDetails_11_en","",20573,], -["features.roomdetails.impl_RoomDetails_12_en","",20573,], -["features.roomdetails.impl_RoomDetails_13_en","",20573,], -["features.roomdetails.impl_RoomDetails_14_en","",20573,], -["features.roomdetails.impl_RoomDetails_15_en","",20573,], -["features.roomdetails.impl_RoomDetails_16_en","",20573,], -["features.roomdetails.impl_RoomDetails_17_en","",20573,], -["features.roomdetails.impl_RoomDetails_18_en","",20573,], -["features.roomdetails.impl_RoomDetails_19_en","",20573,], -["features.roomdetails.impl_RoomDetails_1_en","",20573,], -["features.roomdetails.impl_RoomDetails_20_en","",20573,], -["features.roomdetails.impl_RoomDetails_21_en","",20573,], -["features.roomdetails.impl_RoomDetails_22_en","",20573,], -["features.roomdetails.impl_RoomDetails_2_en","",20573,], -["features.roomdetails.impl_RoomDetails_3_en","",20573,], -["features.roomdetails.impl_RoomDetails_4_en","",20573,], -["features.roomdetails.impl_RoomDetails_5_en","",20573,], -["features.roomdetails.impl_RoomDetails_6_en","",20573,], -["features.roomdetails.impl_RoomDetails_7_en","",20573,], -["features.roomdetails.impl_RoomDetails_8_en","",20573,], -["features.roomdetails.impl_RoomDetails_9_en","",20573,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20573,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20573,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20573,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20573,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20573,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20573,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20581,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20581,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20581,], +["features.roomdetails.impl_RoomDetails_0_en","",20581,], +["features.roomdetails.impl_RoomDetails_10_en","",20581,], +["features.roomdetails.impl_RoomDetails_11_en","",20581,], +["features.roomdetails.impl_RoomDetails_12_en","",20581,], +["features.roomdetails.impl_RoomDetails_13_en","",20581,], +["features.roomdetails.impl_RoomDetails_14_en","",20581,], +["features.roomdetails.impl_RoomDetails_15_en","",20581,], +["features.roomdetails.impl_RoomDetails_16_en","",20581,], +["features.roomdetails.impl_RoomDetails_17_en","",20581,], +["features.roomdetails.impl_RoomDetails_18_en","",20581,], +["features.roomdetails.impl_RoomDetails_19_en","",20581,], +["features.roomdetails.impl_RoomDetails_1_en","",20581,], +["features.roomdetails.impl_RoomDetails_20_en","",20581,], +["features.roomdetails.impl_RoomDetails_21_en","",20581,], +["features.roomdetails.impl_RoomDetails_22_en","",20581,], +["features.roomdetails.impl_RoomDetails_2_en","",20581,], +["features.roomdetails.impl_RoomDetails_3_en","",20581,], +["features.roomdetails.impl_RoomDetails_4_en","",20581,], +["features.roomdetails.impl_RoomDetails_5_en","",20581,], +["features.roomdetails.impl_RoomDetails_6_en","",20581,], +["features.roomdetails.impl_RoomDetails_7_en","",20581,], +["features.roomdetails.impl_RoomDetails_8_en","",20581,], +["features.roomdetails.impl_RoomDetails_9_en","",20581,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20581,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20581,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20581,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20581,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20581,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20581,], ["features.home.impl.components_RoomListContentView_Day_2_en","features.home.impl.components_RoomListContentView_Night_2_en",0,], -["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20573,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20573,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20573,], -["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20577,], -["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20577,], -["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20577,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20577,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20577,], -["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20577,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20573,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20573,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20581,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20581,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20581,], +["features.home.impl.roomlist_RoomListContextMenu_Day_0_en","features.home.impl.roomlist_RoomListContextMenu_Night_0_en",20581,], +["features.home.impl.roomlist_RoomListContextMenu_Day_1_en","features.home.impl.roomlist_RoomListContextMenu_Night_1_en",20581,], +["features.home.impl.roomlist_RoomListContextMenu_Day_2_en","features.home.impl.roomlist_RoomListContextMenu_Night_2_en",20581,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_0_en",20581,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_1_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_1_en",20581,], +["features.home.impl.roomlist_RoomListDeclineInviteMenu_Day_2_en","features.home.impl.roomlist_RoomListDeclineInviteMenu_Night_2_en",20581,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20581,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20581,], ["features.home.impl.search_RoomListSearchContent_Day_0_en","features.home.impl.search_RoomListSearchContent_Night_0_en",0,], -["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20573,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20573,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20573,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20581,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20581,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20581,], ["features.roommembermoderation.impl_RoomMemberModerationView_Day_9_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_9_en",0,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20573,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20573,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20581,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20581,], ["libraries.designsystem.atomic.atoms_RoomPreviewAliasAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoomPreviewAliasAtom_Night_0_en",0,], -["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20573,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20573,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20581,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20581,], ["features.home.impl.components_RoomSummaryPlaceholderRow_Day_0_en","features.home.impl.components_RoomSummaryPlaceholderRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_0_en","features.home.impl.components_RoomSummaryRow_Night_0_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_10_en","features.home.impl.components_RoomSummaryRow_Night_10_en",0,], @@ -1140,16 +1153,16 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_26_en","features.home.impl.components_RoomSummaryRow_Night_26_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_27_en","features.home.impl.components_RoomSummaryRow_Night_27_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_28_en","features.home.impl.components_RoomSummaryRow_Night_28_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20573,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20581,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20581,], ["features.home.impl.components_RoomSummaryRow_Day_36_en","features.home.impl.components_RoomSummaryRow_Night_36_en",0,], -["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20573,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20581,], ["features.home.impl.components_RoomSummaryRow_Day_38_en","features.home.impl.components_RoomSummaryRow_Night_38_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_3_en","features.home.impl.components_RoomSummaryRow_Night_3_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_4_en","features.home.impl.components_RoomSummaryRow_Night_4_en",0,], @@ -1158,119 +1171,119 @@ export const screenshots = [ ["features.home.impl.components_RoomSummaryRow_Day_7_en","features.home.impl.components_RoomSummaryRow_Night_7_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_8_en","features.home.impl.components_RoomSummaryRow_Night_8_en",0,], ["features.home.impl.components_RoomSummaryRow_Day_9_en","features.home.impl.components_RoomSummaryRow_Night_9_en",0,], -["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20573,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20581,], ["features.login.impl.screens.classic.root_RootView_Day_0_en","features.login.impl.screens.classic.root_RootView_Night_0_en",0,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20573,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20573,], +["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20581,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20581,], ["appicon.element_RoundIcon_en","",0,], ["appicon.enterprise_RoundIcon_en","",0,], ["libraries.designsystem.atomic.atoms_RoundedIconAtom_Day_0_en","libraries.designsystem.atomic.atoms_RoundedIconAtom_Night_0_en",0,], -["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20573,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20573,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20573,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20573,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20573,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20581,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20581,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20581,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20581,], ["libraries.designsystem.theme.components_SearchBarActiveNoneQuery_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithContent_Search_views_en","",0,], -["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20573,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20581,], ["libraries.designsystem.theme.components_SearchBarActiveWithQueryNoBackButton_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchBarActiveWithQuery_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchBarInactive_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchFieldsDark_Search_views_en","",0,], ["libraries.designsystem.theme.components_SearchFieldsLight_Search_views_en","",0,], -["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20573,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20573,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20573,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20573,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20573,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20573,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20573,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20573,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20581,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20581,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20581,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20581,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20581,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20581,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20581,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20581,], ["libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_SelectedIndicatorAtom_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_0_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_0_en",0,], ["libraries.matrix.ui.components_SelectedRoomRtl_Day_1_en","libraries.matrix.ui.components_SelectedRoomRtl_Night_1_en",0,], @@ -1293,35 +1306,35 @@ export const screenshots = [ ["libraries.matrix.ui.messages.sender_SenderName_Day_6_en","libraries.matrix.ui.messages.sender_SenderName_Night_6_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_7_en","libraries.matrix.ui.messages.sender_SenderName_Night_7_en",0,], ["libraries.matrix.ui.messages.sender_SenderName_Day_8_en","libraries.matrix.ui.messages.sender_SenderName_Night_8_en",0,], -["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20573,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20573,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20573,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20573,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20573,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20573,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20573,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20573,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20573,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20573,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20573,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20581,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20581,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20581,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20581,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20581,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20581,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20581,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20581,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20581,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20581,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20581,], ["features.share.impl_ShareView_Day_0_en","features.share.impl_ShareView_Night_0_en",0,], ["features.share.impl_ShareView_Day_1_en","features.share.impl_ShareView_Night_1_en",0,], ["features.share.impl_ShareView_Day_2_en","features.share.impl_ShareView_Night_2_en",0,], -["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20573,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20573,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20573,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20573,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20573,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20573,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20573,], -["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20573,], -["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20573,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20573,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20573,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20581,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20581,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20581,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20581,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20581,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20581,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20581,], +["features.location.impl.show_ShowLocationView_Day_6_en","features.location.impl.show_ShowLocationView_Night_6_en",20581,], +["features.location.impl.show_ShowLocationView_Day_7_en","features.location.impl.show_ShowLocationView_Night_7_en",20581,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20581,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20581,], ["libraries.designsystem.components_SimpleModalBottomSheet_Day_0_en","libraries.designsystem.components_SimpleModalBottomSheet_Night_0_en",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_SingleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_SingleSelectionDialog_Night_0_en",0,], @@ -1331,107 +1344,106 @@ export const screenshots = [ ["libraries.designsystem.components.list_SingleSelectionListItemUnselectedWithSupportingText_Single_selection_List_item_-_no_selection,_supporting_text_List_items_en","",0,], ["libraries.designsystem.components.list_SingleSelectionListItem_Single_selection_List_item_-_no_selection_List_items_en","",0,], ["libraries.designsystem.theme.components_Sliders_Sliders_en","",0,], -["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20573,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20581,], ["libraries.designsystem.theme.components_SnackbarWithActionAndCloseButton_Snackbar_with_action_and_close_button_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLineAndCloseButton_Snackbar_with_action_and_close_button_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithActionOnNewLine_Snackbar_with_action_on_new_line_Snackbars_en","",0,], ["libraries.designsystem.theme.components_SnackbarWithAction_Snackbar_with_action_Snackbars_en","",0,], ["libraries.designsystem.theme.components_Snackbar_Snackbar_Snackbars_en","",0,], ["libraries.designsystem.components.avatar.internal_SpaceAvatar_Avatars_en","",0,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20573,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20573,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20573,], -["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20573,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20573,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20581,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20581,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20581,], +["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",20581,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20581,], ["libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Day_0_en","libraries.matrix.ui.components_SpaceMembersViewNoHeroes_Night_0_en",0,], ["libraries.matrix.ui.components_SpaceMembersView_Day_0_en","libraries.matrix.ui.components_SpaceMembersView_Night_0_en",0,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20573,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20573,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20573,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20573,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20573,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20573,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20573,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20573,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20573,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20573,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20573,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20573,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20581,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20581,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20581,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20581,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20581,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20581,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20581,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20581,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20581,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20581,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20581,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20581,], ["libraries.designsystem.modifiers_SquareSizeModifierInsideSquare_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeHeight_en","",0,], ["libraries.designsystem.modifiers_SquareSizeModifierLargeWidth_en","",0,], -["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20573,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20573,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20573,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20573,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20573,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20573,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20573,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20581,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20581,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20581,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20581,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20581,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20581,], ["features.location.api_StaticMapView_Day_0_en","features.location.api_StaticMapView_Night_0_en",0,], -["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20573,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20581,], ["libraries.designsystem.atomic.pages_SunsetPage_Day_0_en","libraries.designsystem.atomic.pages_SunsetPage_Night_0_en",0,], ["libraries.designsystem.components.button_SuperButton_Day_0_en","libraries.designsystem.components.button_SuperButton_Night_0_en",0,], ["libraries.designsystem.theme.components_Surface_en","",0,], ["libraries.designsystem.theme.components_Switch_Toggles_en","",0,], -["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20573,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20581,], ["libraries.designsystem.components.avatar.internal_TextAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TextButtonLargeLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonLarge_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMediumLowPadding_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonMedium_Buttons_en","",0,], ["libraries.designsystem.theme.components_TextButtonSmall_Buttons_en","",0,], -["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20573,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20573,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20573,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20573,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20573,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20573,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20573,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20573,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20573,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20573,], -["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20573,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20573,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20573,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20573,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20581,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20581,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20581,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20581,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20581,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20581,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20581,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20581,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20581,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20581,], +["libraries.textcomposer_TextComposerScaledDensityWithReply_en","",20581,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20581,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20581,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20581,], ["libraries.textcomposer_TextComposerVoice_Day_0_en","libraries.textcomposer_TextComposerVoice_Night_0_en",0,], ["libraries.designsystem.theme.components_TextDark_Text_en","",0,], -["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20573,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20573,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20581,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20581,], ["libraries.designsystem.components.list_TextFieldListItemEmpty_Text_field_List_item_-_empty_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItemTextFieldValue_Text_field_List_item_-_textfieldvalue_List_items_en","",0,], ["libraries.designsystem.components.list_TextFieldListItem_Text_field_List_item_-_text_List_items_en","",0,], @@ -1444,17 +1456,17 @@ export const screenshots = [ ["libraries.textcomposer.components_TextFormatting_Day_0_en","libraries.textcomposer.components_TextFormatting_Night_0_en",0,], ["libraries.designsystem.theme.components_TextLight_Text_en","",0,], ["features.messages.impl.threads.list_ThreadListItemRow_Day_0_en","features.messages.impl.threads.list_ThreadListItemRow_Night_0_en",0,], -["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20573,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20573,], +["features.messages.impl.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20581,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20581,], ["features.messages.impl.threads.list_ThreadsListView_Day_0_en","features.messages.impl.threads.list_ThreadsListView_Night_0_en",0,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20573,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20573,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20573,], +["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20581,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20581,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_0_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_1_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_2_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20573,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20573,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20581,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20581,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_5_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_6_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_7_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_7_en",0,], @@ -1464,18 +1476,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemAudioView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemAudioView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20581,], ["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_0_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Day_1_en","features.messages.impl.timeline.components.virtual_TimelineItemDaySeparatorView_Night_1_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowDisambiguated_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowForDirectRoom_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowLongSenderName_en","",0,], @@ -1483,18 +1495,18 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_6_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithRR_Night_2_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_0_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyOther_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_0_en",0,], @@ -1503,44 +1515,44 @@ export const screenshots = [ ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_1_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_2_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_2_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_3_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_5_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_5_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_6_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_6_en",0,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_7_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_9_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_9_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRow_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20573,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20581,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemFileView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemFileView_Night_4_en",0,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20581,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_2_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemImageView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemImageView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemInformativeView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemInformativeView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20581,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20573,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20581,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewFew_Night_0_en",0,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20573,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20573,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20581,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemReactionsView_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsView_Night_0_en",0,], -["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20573,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20581,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_0_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_0_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_1_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_1_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_2_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_2_en",0,], @@ -1549,8 +1561,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_5_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_5_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_6_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_6_en",0,], ["features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Day_7_en","features.messages.impl.timeline.components.receipt_TimelineItemReadReceiptView_Night_7_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20573,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20581,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20581,], ["features.messages.impl.timeline.components_TimelineItemStateEventRow_Day_0_en","features.messages.impl.timeline.components_TimelineItemStateEventRow_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStateView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStateView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemStickerView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemStickerView_Night_0_en",0,], @@ -1565,8 +1577,8 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_3_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_4_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemTextView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemTextView_Night_5_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20573,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20573,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20581,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20581,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_1_en",0,], ["features.messages.impl.timeline.components.event_TimelineItemVideoView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemVideoView_Night_2_en",0,], @@ -1589,84 +1601,84 @@ export const screenshots = [ ["features.messages.impl.timeline.components.event_TimelineItemVoiceView_Day_9_en","features.messages.impl.timeline.components.event_TimelineItemVoiceView_Night_9_en",0,], ["features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineLoadingMoreIndicator_Night_0_en",0,], ["features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Day_0_en","features.messages.impl.timeline.components.event_TimelineVideoWithCaptionRow_Night_0_en",0,], -["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20573,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20573,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",20581,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20581,], ["features.messages.impl.timeline_TimelineView_Day_2_en","features.messages.impl.timeline_TimelineView_Night_2_en",0,], ["features.messages.impl.timeline_TimelineView_Day_3_en","features.messages.impl.timeline_TimelineView_Night_3_en",0,], -["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20581,], ["features.messages.impl.timeline_TimelineView_Day_5_en","features.messages.impl.timeline_TimelineView_Night_5_en",0,], -["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20573,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20581,], ["features.messages.impl.timeline_TimelineView_Day_7_en","features.messages.impl.timeline_TimelineView_Night_7_en",0,], ["features.messages.impl.timeline_TimelineView_Day_8_en","features.messages.impl.timeline_TimelineView_Night_8_en",0,], ["features.messages.impl.timeline_TimelineView_Day_9_en","features.messages.impl.timeline_TimelineView_Night_9_en",0,], ["libraries.designsystem.components.avatar.internal_TombstonedRoomAvatar_Avatars_en","",0,], ["libraries.designsystem.theme.components_TopAppBarStr_App_Bars_en","",0,], ["libraries.designsystem.theme.components_TopAppBar_App_Bars_en","",0,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20573,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20573,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20581,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20581,], ["features.messages.impl.typing_TypingNotificationView_Day_0_en","features.messages.impl.typing_TypingNotificationView_Night_0_en",0,], -["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20573,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20573,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20581,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20581,], ["features.messages.impl.typing_TypingNotificationView_Day_7_en","features.messages.impl.typing_TypingNotificationView_Night_7_en",0,], ["features.messages.impl.typing_TypingNotificationView_Day_8_en","features.messages.impl.typing_TypingNotificationView_Night_8_en",0,], ["libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Day_0_en","libraries.designsystem.atomic.atoms_UnreadIndicatorAtom_Night_0_en",0,], -["libraries.matrix.ui.components_UnresolvedUserRow_en","",20573,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20581,], ["libraries.designsystem.components.avatar.internal_UserAvatarColors_Day_0_en","libraries.designsystem.components.avatar.internal_UserAvatarColors_Night_0_en",0,], -["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20573,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20573,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20573,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20573,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20581,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20581,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20581,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20581,], ["features.startchat.impl.components_UserListView_Day_3_en","features.startchat.impl.components_UserListView_Night_3_en",0,], ["features.startchat.impl.components_UserListView_Day_4_en","features.startchat.impl.components_UserListView_Night_4_en",0,], ["features.startchat.impl.components_UserListView_Day_5_en","features.startchat.impl.components_UserListView_Night_5_en",0,], ["features.startchat.impl.components_UserListView_Day_6_en","features.startchat.impl.components_UserListView_Night_6_en",0,], -["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20573,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20581,], ["features.startchat.impl.components_UserListView_Day_8_en","features.startchat.impl.components_UserListView_Night_8_en",0,], -["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20573,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20581,], ["features.preferences.impl.user_UserPreferences_Day_0_en","features.preferences.impl.user_UserPreferences_Night_0_en",0,], ["features.preferences.impl.user_UserPreferences_Day_1_en","features.preferences.impl.user_UserPreferences_Night_1_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20573,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20573,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20573,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20573,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20573,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20573,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20573,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20573,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20573,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20573,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20573,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20573,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20573,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20581,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20581,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20581,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20581,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20581,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20581,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20581,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20581,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20581,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20581,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20581,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20581,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20581,], ["features.verifysession.impl.ui_VerificationUserProfileContent_Day_0_en","features.verifysession.impl.ui_VerificationUserProfileContent_Night_0_en",0,], ["libraries.designsystem.ruler_VerticalRuler_Day_0_en","libraries.designsystem.ruler_VerticalRuler_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_0_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_0_en",0,], ["libraries.mediaviewer.impl.gallery.ui_VideoItemView_Day_1_en","libraries.mediaviewer.impl.gallery.ui_VideoItemView_Night_1_en",0,], -["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20573,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20573,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20581,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20581,], ["features.viewfolder.impl.file_ViewFileView_Day_0_en","features.viewfolder.impl.file_ViewFileView_Night_0_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_1_en","features.viewfolder.impl.file_ViewFileView_Night_1_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_2_en","features.viewfolder.impl.file_ViewFileView_Night_2_en",0,], -["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20573,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20581,], ["features.viewfolder.impl.file_ViewFileView_Day_4_en","features.viewfolder.impl.file_ViewFileView_Night_4_en",0,], ["features.viewfolder.impl.file_ViewFileView_Day_5_en","features.viewfolder.impl.file_ViewFileView_Night_5_en",0,], ["features.viewfolder.impl.folder_ViewFolderView_Day_0_en","features.viewfolder.impl.folder_ViewFolderView_Night_0_en",0,], diff --git a/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt b/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt index d6effec06f..33c2ee133b 100644 --- a/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt +++ b/services/appnavstate/api/src/main/kotlin/io/element/android/services/appnavstate/api/AppForegroundStateService.kt @@ -34,6 +34,8 @@ interface AppForegroundStateService { */ val isSyncingNotificationEvent: StateFlow + val isSharingLiveLocation: StateFlow + /** * Start observing the foreground state. */ @@ -53,4 +55,6 @@ interface AppForegroundStateService { * Update the active state for the syncing notification event flow. */ fun updateIsSyncingNotificationEvent(isSyncingNotificationEvent: Boolean) + + fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) } diff --git a/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt b/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt index c9fa31caca..9dd37af732 100644 --- a/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt +++ b/services/appnavstate/impl/src/main/kotlin/io/element/android/services/appnavstate/impl/DefaultAppForegroundStateService.kt @@ -20,6 +20,8 @@ class DefaultAppForegroundStateService : AppForegroundStateService { override val isSyncingNotificationEvent = MutableStateFlow(false) override val hasRingingCall = MutableStateFlow(false) + override val isSharingLiveLocation = MutableStateFlow(false) + private val appLifecycle: Lifecycle by lazy { ProcessLifecycleOwner.get().lifecycle } override fun startObservingForeground() { @@ -38,6 +40,10 @@ class DefaultAppForegroundStateService : AppForegroundStateService { this.isSyncingNotificationEvent.value = isSyncingNotificationEvent } + override fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) { + this.isSharingLiveLocation.value = isSharingLiveLocation + } + private val lifecycleObserver = LifecycleEventObserver { _, _ -> isInForeground.value = getCurrentState() } private fun getCurrentState(): Boolean = appLifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) diff --git a/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt index a61733cc22..9174b92684 100644 --- a/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt +++ b/services/appnavstate/test/src/main/kotlin/io/element/android/services/appnavstate/test/FakeAppForegroundStateService.kt @@ -16,12 +16,15 @@ class FakeAppForegroundStateService( initialIsInCallValue: Boolean = false, initialIsSyncingNotificationEventValue: Boolean = false, initialHasRingingCall: Boolean = false, + initialIsSharingLiveLocation: Boolean = false, ) : AppForegroundStateService { override val isInForeground = MutableStateFlow(initialForegroundValue) override val isInCall = MutableStateFlow(initialIsInCallValue) override val isSyncingNotificationEvent = MutableStateFlow(initialIsSyncingNotificationEventValue) override val hasRingingCall = MutableStateFlow(initialHasRingingCall) + override val isSharingLiveLocation = MutableStateFlow(initialIsSharingLiveLocation) + override fun startObservingForeground() { // No-op } @@ -41,4 +44,8 @@ class FakeAppForegroundStateService( override fun updateHasRingingCall(hasRingingCall: Boolean) { this.hasRingingCall.value = hasRingingCall } + + override fun updateIsSharingLiveLocation(isSharingLiveLocation: Boolean) { + this.isSharingLiveLocation.value = isSharingLiveLocation + } } diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt index a473e6bd22..232116b385 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/SemanticsNodeInteractionsProviderExtensions.kt @@ -23,9 +23,11 @@ import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasText import androidx.compose.ui.test.isDialog +import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import io.element.android.libraries.ui.strings.CommonStrings +import org.junit.rules.TestRule val trueMatcher = SemanticsMatcher("true matcher") { true } @@ -48,6 +50,14 @@ fun AndroidComposeUiTest.pressBack() { onNode(hasContentDescription(text)).performClick() } +/** + * Press the back button in the app bar. + */ +fun AndroidComposeTestRule.pressBack() { + val text = activity.getString(CommonStrings.action_back) + onNode(hasContentDescription(text)).performClick() +} + /** * Press the back key. */ @@ -55,6 +65,13 @@ fun AndroidComposeUiTest.pressBackKey() { activity!!.onBackPressedDispatcher.onBackPressed() } +/** + * Press the back key. + */ +fun AndroidComposeTestRule.pressBackKey() { + activity.onBackPressedDispatcher.onBackPressed() +} + fun SemanticsNodeInteractionsProvider.pressTag(tag: String) { onNode(hasTestTag(tag)).performClick() } diff --git a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png index b5e7419267..b45afb67bf 100644 --- a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:48fa7b1415694f0a7ebb3de458edee8792f5643f681cc25627560f2e3d8ba491 -size 16331 +oid sha256:49731638f35e9c7583ece7122e3690728f3d4183a65e2e49cd270d02fb93ac70 +size 15950 diff --git a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png index 1c8ce2991d..14fd900451 100644 --- a/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.call.impl.ui_CallScreenView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ebf559265b2cd4ebba7c5439b759365ed8d31532988bda5d8c76bb7c8d76dd68 -size 14892 +oid sha256:11a77776662896532ef2999e3b90aa93b3459bf9b7a5f461c06ccb3743612aab +size 14738 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png new file mode 100644 index 0000000000..c431ee02e9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Day_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aaf113646fa3a8ffd57528d3e97eec05a8d80b99a3bbd7770266353dbe6abd64 +size 10217 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png new file mode 100644 index 0000000000..e3a3776919 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.api_LiveLocationSharingBanner_Night_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53d9deec2a6295fe0155ce2986463a3b598436c0515ef87e0905c62c25970420 +size 9647 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png index cae8f75b66..afd74655d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:aaafea9efc1000495ee469797239b82193844caa3d6f98c0c3a4344a536a1798 -size 17155 +oid sha256:c9ebf3725fa875994cf1a15b30e2d4d533c2a9281f0f7d5d9f83f8685ba384d1 +size 18637 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png index 29f70fc9b1..30fad74bc6 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.common.ui_LocationShareRow_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f113f8979679c0673e4cc1f691140bc570b6826bea23eecc403f2fbfd3f6d09 -size 16460 +oid sha256:65c321199578618012d27afe478c0eaf6a67c44101e7d1d1c51a4c6c1fa9b93a +size 17897 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png index cce7a48382..0c9a67252c 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a97492422d54a6d6666c1ade693dc9b63bc9ca07c17d6c1f787c081984c09f68 -size 42470 +oid sha256:9f3fb75974ce37fc3ce5e303ab5573a0d9a769f3c079de5b0f6462b40e53c1cd +size 26713 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png new file mode 100644 index 0000000000..e8ae396119 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddaf978cdf3e70b01fbee75e7e7290fa390e749b48ae192fe7da0dcaa9a1d4dc +size 38417 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png new file mode 100644 index 0000000000..cce7a48382 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a97492422d54a6d6666c1ade693dc9b63bc9ca07c17d6c1f787c081984c09f68 +size 42470 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png index 541b2a97e1..06ec0c10e9 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:038e12f3caeef6ac8d5389b7cdc68138e089dcac335d0a5904adc55c9bcb7b1c -size 40642 +oid sha256:4031ae26bb8465a61021c15b6166a2186f8f99d7a4dbad7bb28aaf83493cbe69 +size 25907 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png new file mode 100644 index 0000000000..7761c87d2e --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9ed7610fbdabb3e88c35e2832d06566431d472ad95890c2fdcbb6d1b43d8feb +size 36751 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png new file mode 100644 index 0000000000..541b2a97e1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.share_ShareLocationView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:038e12f3caeef6ac8d5389b7cdc68138e089dcac335d0a5904adc55c9bcb7b1c +size 40642 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png new file mode 100644 index 0000000000..5669a59d24 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8665179304ccd2e0acf517ddcf369c4daae51c41732ee1b9618e3bedf38aeffc +size 31643 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png new file mode 100644 index 0000000000..265044a0b2 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14300f3af0bc8c003ce94868665547ad439826b47cf416f1a062ffa4a1d7e793 +size 15782 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png new file mode 100644 index 0000000000..ff95140047 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88354d222679723cadfb76d2c4928fad78e17fec13514c0e4712e6f877b1a0c7 +size 29627 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png new file mode 100644 index 0000000000..4bc9f6653b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d505c4b2323dfc67c1b7e119960ede5b97b52d6c453610cdbb01efd485730aa5 +size 15369 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png new file mode 100644 index 0000000000..8b7fa8b77c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80246e3957a0e3f98bce55ddd6d8fe09b5f140eee3837d80ca20253f6bcfb876 +size 37738 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png new file mode 100644 index 0000000000..266dae3c81 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Day_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60dd90eb571f473b78ecc629573bcf2faca02819022bdf57f05cc8b0876f4ab8 +size 31440 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png new file mode 100644 index 0000000000..8a8d15acf9 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d60a8caa2441ff0618636d307d32d0944bdb77fb3b579c0959dc951b0318ad72 +size 35429 diff --git a/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png new file mode 100644 index 0000000000..fe27573765 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.lockscreen.impl.unlock_PinUnlockView_Night_9_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfe8b59b8d5d7a1c33285072dec437060faae55bfa2a42687bd8895dd90409a6 +size 30310 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png index bdb2a689ac..def7635efc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82ed52f907048490ffb63ea9b33274703c1d92d4131cca0320816cc6949bea5e -size 113727 +oid sha256:b9f2f0e8ba6829cb3d83dcc0c6d3ed5a91a0346771f84adb6731ba5fdac01f4d +size 122009 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png index 5d9f6ab2ba..c6a916891b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae3a754c163f83e69ab062c8e638a6e620948081d70105ddb00c32dda7c2ba74 -size 119927 +oid sha256:459141f4442bade537f755d56fe0b4569980a26b92f23409c477802462084b3c +size 122118 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png index 01d01e6806..07613eb447 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:757d555f948a637952aed4b0ad2745212f6a9ab279d172b0a1649fdf547c5a0c -size 120027 +oid sha256:7f85b9e88dca466b567769291fb69afac535135c3a07f412d6b8203968460519 +size 120940 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png index 6962ed5f4d..f06f86068a 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb0d86877e5d049d618836846cd8ea97b40d1d66e7bd8d50639280fb3e829372 -size 38499 +oid sha256:00da192b3b46897c9d50986ecd84e07332cd2b490ebc8f3893a9497e72f18af8 +size 41478 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png index 7b0ba78a2c..140a3c3446 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b41879f5159a126b0641c66bed13470756a914cc038dd239d40d359661784b71 -size 40696 +oid sha256:c5a9f9104c9544e32ab0ab67ce03dcbef51e8613c1444aec866ff9bf60f6d241 +size 41683 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png index 8ee52bca11..4cb5fc6e48 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:38fa52e6e755d86aa79a029427f04146a3939ac2038cc15717f5aec84ce3be20 -size 40870 +oid sha256:c015bae5b3ce8c4447c62a13fb74d855c23b0e41bf0b128a1834d30781c0d1f8 +size 41110 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png index afec980e10..e89697a8cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3624fe8448ae4af2481e2023a978ffab2d69f2784b7cef41e5ae2e2dbe8fdbd5 -size 17804 +oid sha256:5529e89e00208e38522f5206f5b8d304bd472b27071cab4e0d3c2daf3cb64db0 +size 49741 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png index 8f7f14e64a..37037907c8 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bd02d39619efbcaa6d96f1e75a0d14a572c43e60bad0c3f84d6a5a48b6fbda1 -size 17395 +oid sha256:fa29aaa82f21912dd5147ffb6fdc457fd5880e8be4abde4f0177d0ab1a412fe2 +size 48245 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png index a63b53d2c1..157e74f7f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7fdd2e68114457368c5d19fe117b2d5a86a02ca475925c9fae0269ff92f5144 -size 66312 +oid sha256:dc02a7c7b38753d9509b3cb0fb2eb0e29b6d6c79b8471ba4dc7dd5b81b13d15b +size 50892 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png new file mode 100644 index 0000000000..a63b53d2c1 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7fdd2e68114457368c5d19fe117b2d5a86a02ca475925c9fae0269ff92f5144 +size 66312 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png index b8d8a2cf4c..e4a14ae551 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cb21bd5e7d348d1d07ca4b6a360f26a4735cc9760fdd7e3b4b1bcde32da6f08 -size 62655 +oid sha256:39430896a687266d7a60890fdac5dbca6d36c87fe30d07619c9c50e23c3f77be +size 56972 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png index 157e74f7f0..b8d8a2cf4c 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dc02a7c7b38753d9509b3cb0fb2eb0e29b6d6c79b8471ba4dc7dd5b81b13d15b -size 50892 +oid sha256:1cb21bd5e7d348d1d07ca4b6a360f26a4735cc9760fdd7e3b4b1bcde32da6f08 +size 62655 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png index d2b5044048..74826e1e9e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:52441a5e250b027ddd40ee32754a63c6206762084f47ecfa7e057e2ac77e78a8 -size 69120 +oid sha256:805245ffe7f4e99a0f5927b89bcaa6ab8eaf7cc603d352b14b8109e76eecbdf2 +size 51742 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png new file mode 100644 index 0000000000..d2b5044048 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_11_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52441a5e250b027ddd40ee32754a63c6206762084f47ecfa7e057e2ac77e78a8 +size 69120 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png index 6e371532de..1ad21c4d64 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:86273e812cbc6245527c3d1f138111ece99375aec0d68728882b656b01687bff -size 64392 +oid sha256:289819914863942caad5202131efddd9b880b4af64a36d4b45fb547b5b1ec47f +size 55916 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png index 74826e1e9e..6e371532de 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl_MessagesView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:805245ffe7f4e99a0f5927b89bcaa6ab8eaf7cc603d352b14b8109e76eecbdf2 -size 51742 +oid sha256:86273e812cbc6245527c3d1f138111ece99375aec0d68728882b656b01687bff +size 64392 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png index da80c7af53..08966f9b39 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:645a7fb89953ff6e72119a105ac966cabaf8ca6a68f3023534301e3471b942f2 -size 49262 +oid sha256:42fd1d9b089b026a9edf1a0ecb71da47a4517062cc19f61e16e70f9b3276ab30 +size 59658 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png index 6aa030a83a..25f2f73063 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea52fd146c53b690c1273b090c6b66701a8f40d80eb1dc693898c3dbf8b24def -size 49115 +oid sha256:314ffd2ccda8d0315a27e0cf08fa6d158ddf38fa0903e1e8d7fe45361254aa0d +size 59525 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png index a31686aaad..c9b289e9d9 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf3e4ffa06a77fbaa9dc9985274d6b1324fb023f5eeb2b9d229af0854b41e236 -size 49095 +oid sha256:dc25ef0688d2aa9be1fcade1dfa282b243cc3c45bde01d3571b2ad9278dcda74 +size 59509 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png index 421367fee7..3398dc3826 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f68a09667dc19c935decb5b640bed2410dd16ae88c0d0ab6ca410225e48a87da -size 49111 +oid sha256:229b570a3c938e75f5d7b33c7fec89be9582ec06aa85dfa587b995219b145e88 +size 59517 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png index fbcd0538aa..6767c03276 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5defae968cccb0e78ceff23912a364cf72f9ed61ea6ae3cc9770af9c39b05f9d -size 49035 +oid sha256:9c9caa916637c212f2cf1e5d175a9cf096b83606e1161b7c2bb1c8ddcb142e48 +size 59363 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png index 7a3e1e9682..e9434a4041 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c590f67875f9bdc460ab82b59cd3c9e11147bfadc59028552071b64fd440f211 -size 49259 +oid sha256:296c4b7449992b4aaa478038db9b6dd4e687ca05f82cc351db258e3f178adb6f +size 59656 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png index 9c788eb3ab..dcbfd047c6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d48af05c854a8f313f10aaa774e4268756dcf7e0c2bea0e138dc6cd84137673 -size 48995 +oid sha256:f13aab730039d52c1d92e5ed3ad601095cf7c8b3bd76ddf2303f2006ea6f6092 +size 59193 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png index 9d375b0b74..3526e1e6d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1507eeffcfacfcf6c84494f09d89ef3478748ae31f8fee4a9922e4188ccb454 -size 48563 +oid sha256:961959403b1763abd537e05865d86475161e650e61e51e65202522d08faad55b +size 58771 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png index fac0ba3da5..c1707ebef8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4146fd85887aca1a0a65ef559976c1436d1fc2b0de522295f27bfaef1d904ea4 -size 55410 +oid sha256:2e5df1191bf18d6c922ca3d2a22584c98c4b871254512ea86cfb324fddf8a2d0 +size 62520 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png index 9feee4d98d..880c259789 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b832525da2a7744eff8165c842652bfff4742b728b000b1c8ef8be81bca75efe -size 47052 +oid sha256:ad35559b964b2d1197b256348e175a8082bffc9247024a546eea86655c9c0d8e +size 56855 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png index 9a4a40c0e9..c3e7180e3b 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ae8264008b6396f31332263472c910b492fffdb9dbf7d0186b44a272476c02c -size 46903 +oid sha256:94b94eca0502a081fbb862c426b5063275ac948c8d998e34f40e362a82591d75 +size 56707 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png index fa74fd4b96..bb6e078571 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4842f6e88df23ae0050f0052ebe9581d6c19ac5e29a0c553716012713fbb00aa -size 46901 +oid sha256:46bd8afffd3a9c4cfb92c7d9ea2c2d0a3c4942115a80809d6bbc16037e2839a1 +size 56705 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png index 5f9af21b6e..c0ea01e3b0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7888dbb0ed5460c54796a6b2c232945bd4449e57feda4aed89ddce097a3c35b -size 46911 +oid sha256:5fc17122d1466b14e85a49165bd3b462756181ec26cbce280437f015734c8e40 +size 56716 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png index fe34c6d5c1..efc3e893a9 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:215745acc9dc0c86e239acf614c94f1cd46e96cf1b6dd7cdca514d7a4a82f835 -size 46742 +oid sha256:12cb6a8ee6846a0f44d5e14599fd7c6dbf97da97d35c6b6c83545d601a246efe +size 56563 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png index 9df6b272e4..7ee27433d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f5d099940f91cb3e520f6eb6cbbc075bc57817f3e46e3f9fb169a36b408388f1 -size 47046 +oid sha256:1546f59a5be6b5f8883729c4b83005ebeb990188a86c100ba384da46b2a1da7e +size 56853 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png index f56d4e2115..aae9546e31 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ce9c49a9d136d3bae5fb366fc47d3f48f8fabbe6963d0e53166dc1a5ec4cbc20 -size 46695 +oid sha256:714782c0f439f933f6e0127ccf54b6e09138fa23d44a3596017a23665131c119 +size 56498 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png index f19645feef..efadf6c0dc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed86c0b3137dcd650d7ba65d7ec009146234b4e0b983b1ab8b56974000698201 -size 46242 +oid sha256:9a58efd0afbc84c88d8635738d3bb25826c4d25d790d4eaa1aba0e9efafc3b56 +size 56043 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png index 2b725b9e8f..1547c5289c 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dbdf230e73c3fd93787030d6f5eac65b6a8131bf2eccb07fcd8474f191b87b06 -size 52563 +oid sha256:9d502f4f9ccf2d3eff614d9ed2b751a252acd05c1bf5cf4a8b11775c45725c3d +size 59427 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png index f9a16c247a..1cea623bff 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2d57215dd58ace85ad235fb7f95ef592bfddd3c21afbf183bb5d31fbf772b69a -size 48900 +oid sha256:7c80e9985aec6b183e33f12ecb884753d1b8f67927d6d5713ea946ea8f5d6dd6 +size 59300 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png index e662b2dfbe..d32d440b79 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32926b81da50838d883edfd157e7d12cc3d43991556f87e61702b74e693ab6da -size 48798 +oid sha256:5dedcf20e368909de0a6cdeade437bff06b38a1f1b6aba3355968983f1387018 +size 59201 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png index 5ac95223f9..6f672c23b7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0594480e59710892e480a83c1352a501504ae1bafb4c5c6b672c7dc62b3e75e1 -size 48801 +oid sha256:a9023d044daba4573bb9a3ed4da598bfb5c27081e4f7a75757a4796bdc44573a +size 59207 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png index ca2e552c10..54bd893d1f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba828796a14ee9e82e01e98a89067649a7f3438a2fcc8e3ce5f69e12e86f86b0 -size 48777 +oid sha256:77eb9f159dbfa30e6f750500c2adf21b18cb5f1dfb7a574be68683db24803225 +size 59174 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png index 6f741da48f..e945e52dfa 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ebb88fa29993c785e6ca82543e7eeafefe365c0018a4f22852b988dc35db4a5 -size 48716 +oid sha256:3dca50c7a0f0d7ce96388a01456871decc76285384d2573161773219c79fb876 +size 59060 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png index 1a12af9468..02c571c605 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2521e5352ee6030f7a0fd8304b19f6a7a95fb6364d43f412eeef03799c8c0f76 -size 48901 +oid sha256:fe4181c3e521f1f788dd06e3cfb1ca078655852415dfd4f26f5480dd47bf084c +size 59303 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png index 962991ff8f..7da66a622f 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6dfcf074e7fa4813218f4bf9e472f706c5581e6fc5c1f7ea1eb9ec422172190f -size 48713 +oid sha256:18602ce14232fd438450782a564354c38ebffb0c56d0c3887d88c47cae53dacf +size 58962 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png index 8917220310..015ecaf7fd 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3195a1871862ce32cdcf068608a565c56e794ff66f14473d5f6355918db79b6 -size 48402 +oid sha256:c3ae0af5031f7f850c40fa6560aa6d70127e006931a3e18cbee04acd7c7aed57 +size 58526 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png index 5fc76943b5..19d1ae2ca8 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f71219202890afcd4f43b5f57cb4d555b723df48f71848b64c8db415067d1d4b -size 55044 +oid sha256:a980564b6406bbe45b9a170a5744e45c9e019556587d433e5fdffd8ab6f1c6fd +size 62034 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png index 5f0cdd8eca..43a49f7320 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsA11y_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33d583fac967f383a3d3535c4ac38aaccdcbf4a1d48323ff375a239dbce81838 -size 83494 +oid sha256:34ce2f0451fb1681648c91771316256e67b1f295f4deb97f6115ae593d82f2ef +size 83472 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png index d674b1ad00..bb68ee4d65 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ad7b9331a5d504b8d2145c4428e6b64ed838b371f1aad5c288e5545f8a20f1f -size 45464 +oid sha256:eeb2355a693a7ac522028833fea4f0506e1b455e4aee888ed314c2700a9a87af +size 45454 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png index 2567512ca9..77bc91df06 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8d74ede198f221b1138ed49bac7e02ee0fefbccd38735b09237fda95a78f6bd2 -size 44174 +oid sha256:b45d35b68d232fc5cbaf3b01156127a77618bcf2197375ad42f61bc7ad8ec400 +size 44161 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png index ee9fcd2088..9f23841e1d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3f483a9e05278928f806f9534720c121efa77bd11b93ea6afc8b543f51a6d7c -size 43171 +oid sha256:6a7efaa997737bfc6db898987b78077ec3c8039a6d0cce84d770bcabcbdc815e +size 43161 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png index 724a99374d..308c764795 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3045102b9695ce3c095ac81e3d3d26dbf182d433427903e280189613a74f2984 -size 44758 +oid sha256:a8de9a9297383ff1ec552304a49040c44236654dd16ba9ae5f54fddf3e14c617 +size 44764 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png index c62a4e99b7..13403ea92d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2bbbf23895558745ebe4fab7faee8ffb4acba07f48b652cc130c78ddf89bebef -size 44684 +oid sha256:ff4c856028887c1390df7b313462e37e0723ff98b9f92aa769b2fc9133ab6ec5 +size 44673 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png index f23e6e5532..59ac3c53af 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1f72fb044fb52f226600ad2eb3344e8122edcce15c75800fb483f3b93a1c6e26 -size 45092 +oid sha256:162a9cd8b10b8ec7c33dc926c63d2d04986ca0e29a6cd036771ffc137176e28c +size 45079 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png index 47f40ccaab..9d934ba726 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14261c716c286b17ee2afcb652378f9703b39f67b219256f6ac3cde61cd50947 -size 45589 +oid sha256:fcd3e86c18e34e96a2b535340a27a8cb248d48697ce75d1c7c62cde27b3e2ccb +size 45577 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png index fd5b8fce76..cfd42f8af2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1b1c3f8db4dc58dcaab91f254da2906138c09c65d4e57a77a5be9af371aaa5d -size 44944 +oid sha256:d5a20887fa9a6dd7c96f328f24608e1fcea0326b60cf8a7b43e2387fa19595f5 +size 44932 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png index 5491a33e2a..b45fd6c6f1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5d3a4bd5c340c0d439ccd7d7e24f372d89255a775a9497e5d9b8847354cafb6 -size 44236 +oid sha256:8087a634dd7bf3893697d8ab599f9694169e878b4484b0d8e9821307a8423d63 +size 44243 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png index e44f676f01..ddcd78552d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6d9a464a1bc24dc76d1a10ae835fb24839b521ba446a1adad3e70f4ae5f17857 -size 42076 +oid sha256:f7b9375965be172b7a1a6b00be38c66dc5f73d7d76f6b07fd1cb8defbadae840 +size 41554 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png index 46bb9b0a89..669af01562 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29592dcede3af29136c857b03975c2697470682371ac5d606f2e6974f89ea268 -size 42030 +oid sha256:7890cc2fc8e722bfdee5e1c0cdda335c386a2e70a918b710a44a788457dd8497 +size 41507 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png index d58516f709..6b89622e9d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:676908cf3eabc3417f228dabd2663bb0aa3d903d1b6f0e2fe770bdd6fbb48af2 -size 40407 +oid sha256:e7b4d5f81f605a0858994e50d72fbd17d2f82e0b2e4673ff9baf6e25a103ef55 +size 40392 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png index 7cc47cba6d..b0a44326fd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c66ebe3c16933495fe33596036363f95e20654b6ef5ee822f594a34531ea640f -size 45211 +oid sha256:fef854b4c908e206ece79491c655fbf0fd5b51883f3d77045c579664331b9058 +size 45195 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png index 8d4880b59f..637549dfc7 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:de5ccdad3e08ed4fd4330697ad6c7085d5553cb889b7b7c12879aaaa6b34c1de -size 44953 +oid sha256:dde778a13f36958fefba950fe0d3470b7277d22fe4eac189c77b0838b3728ef3 +size 44940 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png index 52e66c38c8..cafc853f58 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e215296d864d34ceacaa53e7fec452643b63d72b253074eb50617bab50915ad1 -size 44670 +oid sha256:d5870cd12f6de78ecf72a9dc8e3716e0e3476ecf2f29647fc1eca900f5e030f9 +size 44652 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png index 2a765938ad..12efcf7526 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae13e58b01e0e43591c0374474b33fea60574a5d8b22cb57092d15637dc58baa -size 37920 +oid sha256:1281394671737e78232cb7d9785b57b8ef2ca50c125f0c0854d101d27efaa939 +size 37910 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png index 8a7f2e2d75..3d6f26c63c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0cc874a4ba2b8bd0f0b7e290d0ffc67e82d1222fd287360c3321143d5f87ad4 -size 42369 +oid sha256:ec2b5711ea9ffacc6aad4f7b16efdcc78603e9eaa9d33abfaa0d867db5aead67 +size 42355 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png index c8d3e8f6fa..90dd2364d3 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a5bb345d25a8b90a34708123fc6ba72dd6aca2c09ade4c26b29e9168d65e18be -size 42466 +oid sha256:4adfa037ff619098067d03f252ba0af1c3c89553ea0c81dcda41f7f0b655baad +size 42450 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png index cdb5f92f18..31daf341c2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1d4af8779d9869938b17f26b155c584c10d119479c62918d5b819a0db30acac -size 41720 +oid sha256:105399c3ca12de9e911ccf7b4aaebe87bffeba45b1740d067b5b8e67c5647952 +size 41196 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png index 1e0b3070ee..3309d53220 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0fac98b00a99771b186e8146b98ab63602be7b4c5cc9febc3ca821c1d5cd6a1b -size 42700 +oid sha256:5da1fef365731946e08a38250187fe6f3108aff466d7771863c0ba52fb5b7728 +size 42254 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png index 478f3dcb3c..fc66173002 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cb0953ce6c69ad2e49213bf0dbff76a87505f88a092660b71d97ad1e75a5344 -size 45766 +oid sha256:0d5b8a9f7bc2e7f654b018b2f66b5971c21326dd6b64371f330299649daea4c0 +size 45755 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png index 37a67e7aa0..d4ff65b44f 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0f655ed143e7b894e37d99fc64c75d44e6483e830055e04609a9da36830278c -size 44670 +oid sha256:2dd6b524bd146b4e66621fea59515e6784055f52f6d1d08c393b5be208e5f29a +size 44657 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png index b41099055e..4264857e69 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetailsDark_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac26ca718f2118d88315704ce4bc7960983ab2ac0c394199da2c5b3feeec4438 -size 44688 +oid sha256:73a27b8df68182a3d0ae4872a14688ae10e5651ec85490c1e46186acc2c60028 +size 44671 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png index 836386fc75..f0751a53cd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a9c05a4ace7dc7013e4b02b5e652296399cb2f391ed4bacb2f74d06b68c4be4 -size 46436 +oid sha256:9bedc6d0b55d94586de728cb4039303c9ecbd8b3a090c401331ae1bf6e0ba426 +size 46396 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png index f3ee29437c..f5f4d4cf3c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:997444daf4024495291014f1cae1cee2ba389d160c0ccae706b120dcd908996e -size 45024 +oid sha256:d47a7207e83fe770d4925b91b4bb0eee6cb2c494c46b1f3d5d6d0720464392d6 +size 44992 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png index 5ccda85a79..54890aa7bd 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_11_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:527d2c4574c8a5f6946ee94415e30152fdd9e153fd7651b5a40df789e8694d72 -size 43969 +oid sha256:605ea373238bbaa4d3820adf13bf3896d9a5c5b6ceb6c022a7f3b8ae817f921f +size 43927 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png index 60753106e7..385ca39bc9 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_12_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7da6bfdf7bc9878e1850f8a443adae82a3a4b0aaa5574cec74081ba6f88b879e -size 45622 +oid sha256:c4dab72328925eb45cd529913972670587ea4257d2ff7affd708295d68e783d7 +size 45579 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png index 5549792942..064cfc5b27 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_13_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2e253e47f998774da8443926990526105fd918b79040955a3d884558a110db8a -size 45538 +oid sha256:76cc029a07c0fb568d9e15864be667478cd9927095f66ec2f590a1466c58a291 +size 45497 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png index e5dac7dc72..3bcd7d1de4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_14_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60a989450ffb8ed428d5dd021573b821d238a06f5515f21f9d50b855889ad985 -size 46022 +oid sha256:42a8b9b5abe3a5a3fe61e27924ca75ea7925e857005d5de3cd3ceb81500f73c2 +size 45981 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png index d4143895a2..5dc96aaa2c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_15_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37e6049854cd5aaeb50f38c4604e631fb561f0f309d4c58d41becf69a01ca036 -size 46596 +oid sha256:19cc2df1da3b685668afe309bd305d5ac8447d0997c7ad902685d44daa26239f +size 46556 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png index 03bcda4666..2b4718d729 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_16_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05a841f7590a33ffea5b09ffc0975bc9090b03cace9e22c330965ce773431211 -size 45849 +oid sha256:5625bb01c24d969adeecdb536e145ba549ef1c10d99e16f7a68c3bd577fbefbc +size 45804 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png index 19d509d513..4f40cab65a 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bc90cce90b0648a340e332276fe4395aec673408aaf938bd0d744d45c89dec2 -size 45396 +oid sha256:3bdd0b00fddd9fc62b5c9c97b5ff766591c0a1822730bd249059ed02508a65ee +size 45353 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png index 8027c68a7b..74405c8661 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_18_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c3ab8eeb4123df1feb35b4d9d9c7fbf166be943edfeb9fa23ac6549463763b10 -size 42853 +oid sha256:fef392cb892bf6dc746ed59f1279bf9558536ef439715d1834bd88260739949d +size 42441 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png index 64acd4e843..dd6c6a993d 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_19_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3eee4e61c8676a547c3ccbb1d6b9ea2ce0ae30286012de6b3a4f912b908d2e0 -size 42722 +oid sha256:c9b7c26c5f0638dbe7731e239fc16bb2ba4330986af7218688a3a12ede2bfd9d +size 42313 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png index ef06cd3451..02be5d5da0 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02c734eb60efab5050988331527aae294fc6baf0b110e3395103429a79ba059c -size 41424 +oid sha256:4dd437c614c904bf210e5b51fe017f26cf849e7572b09966e834ac6fd429d347 +size 41380 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png index 9462f1336b..7c037817b4 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_20_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:389fcb65c5334f31b3d66731de2c65128d0a17e7380ca7c45be8a36023719732 -size 46097 +oid sha256:380fbdd2caa485b9fe84a331e64139ccb23998ce1d95158c6345364daa3810b8 +size 46048 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png index f1f9639eae..7b74e5750c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_21_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:567cefb525795b66704ccd1738bfe08247004814c947f6c60801588304c768c2 -size 45835 +oid sha256:c4610f8488c8c8edf05e2cd3e09470660b2c4db14650907c28367d2b38bce852 +size 45792 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png index fb830369a5..a2e1108c0c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_22_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f87512e18ca91237141d97ed03f4725a8a671268daf50f0a8049ee34bdc42a61 -size 45503 +oid sha256:efb795d2808d7ae5e38eda42105101dce377154c794844f752e4cb80dcabd681 +size 45462 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png index 25bcd31599..2d38f9d8b1 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ced1cdb2e11bff01ffce233ddf6cf826d6db266739abcd022f83b58d8bec012f -size 38785 +oid sha256:7dca0800e7e68e65bd27814b4c86123da40385d6e85153e003ba58ca7689b5f8 +size 38742 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png index a64f6a2843..1fc42278e2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cfd96490ce4509620efd7be72e6ecca219eafe73050417c0c3685339444457f1 -size 43060 +oid sha256:351183a1b0fb44dc42c790a625ee6aa5740b27fa95b138252b72bf67268f5a16 +size 43015 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png index 92b2b86922..da0c4a9dde 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db67d40bae68ec1ece950a06f618606fedc78aa997743b1804db4b69848ba65b -size 43381 +oid sha256:31f92cc4d97c7129bc37da51e6f0a10612d4f61803762b1709c5d72f1cda86f1 +size 43337 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png index 8b143f6b5c..e6cae695cf 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6cee9f291a3257f3960ea5d1490f3f219bb0d42b01109b9b398b941524b85971 -size 42383 +oid sha256:8d6a5102a9dd44a6a15dc6b40ec422a115a302506a2b3808a1df84ca34cb323e +size 41972 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png index 2f72417b73..a1947b9c2c 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_6_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd455b5b492eb88bde4e985ca01ab97e23a337d7ac478782c09dbb10803960f2 -size 43430 +oid sha256:1538aa1f1313df1f6cbbc0ed7ef92d264c85b7de0080492a7cba19bbd235131d +size 43100 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png index a1071426b1..ae9d249cb2 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_7_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:79ac979bcc0339ed30c68c4617f082a9398edf657cc3aea1c80df04bd4b8bab2 -size 46724 +oid sha256:4e15030fc182998a37493228d91c888d6b499b6a684b1a4e15d402c9156a40ba +size 46678 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png index 36a3defc1f..214dee1111 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_8_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0d71c5e3a8dd2defe2dd37fee1a22921f49bbc9a52a766e5ad082b6595c6ff75 -size 45577 +oid sha256:b773cce165a6410140afbf0daf3ec526233b97ea707811a3794e591704237398 +size 45536 diff --git a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png index 6c4e522988..41946442cb 100644 --- a/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.roomdetails.impl_RoomDetails_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ada1e17913092a5e33b5f422a41826dd711102cfb5ab396d5d323e8e0f0b6589 -size 45590 +oid sha256:f28bec4fb21e827f3467bc08ab0f33e917cf76360903b6e7df6282a7589cae7e +size 45545 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png deleted file mode 100644 index b96321378c..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatarsRtl_Avatars_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9dda468dafd8eb072ad7f3b731e55fbd1f8a4e11e8765f566b929b1d367fd0e0 -size 13693 diff --git a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png b/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png deleted file mode 100644 index 097602787d..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.designsystem.components.avatar_DmAvatars_Avatars_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:69e9858a04efe0160908bd0b85990dce8e983db33408ca58752bd4dc1eef6861 -size 13576 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png index 36ecce8294..2e580e55a4 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5aa3bca6cd248ac4725fb35aa11a465029dc534b8b167aedbf3e9bc240577e9c -size 654171 +oid sha256:4e8ce597c240a7e72b6811537b6fd24e1bd38714db0ce074377ab3f16eaf0436 +size 656958 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png new file mode 100644 index 0000000000..b18a209110 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_18_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46d390cfe8d41536cea5e90cb38aa547969ae24d82027c02cfb71c4fbc780247 +size 667948 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png new file mode 100644 index 0000000000..e22d5b8e72 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_19_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bd4f0133fc3a4a159e3eda1f715e4140464b7c67558c551216546d4688f21bc +size 669143 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png new file mode 100644 index 0000000000..1023508292 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_20_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:178de2176a3932665897486ecbee622083af2d5939f4f1f7f0bdc4667a61e36a +size 668061 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png new file mode 100644 index 0000000000..9fa3e43792 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_21_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc974dfc6206f389153477d287a69c401ddc154a529cb892227a743acee8ac50 +size 668212 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png new file mode 100644 index 0000000000..081ab9a80b --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_22_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7ac632f2062aa4a13ee46fd2fef6d9e6be25270f4790247131231163670cbe6 +size 670668 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png index c63d5a9110..d122817b15 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bd5b76aefb0fde0605556e78c7286bf8ee8dd465def0e3095ebc97ce3427eafa -size 666239 +oid sha256:21b8289db279172f042fa902bdbdb70d87104d342a1140357bb1ac2bc18f6590 +size 668482 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png index d404456119..797c1cb2cb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f6870b9c1a5aad4257aa4bd7b13d0be5bea281778061d71c711495aadfaafdb8 -size 206057 +oid sha256:f72964447f2fa66e8df38fcff4a84ada1cf62e1646a2e8a00c61f8f151abfa8c +size 206507 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png index 5b167203f5..be398e06bf 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bddbe3b0e66e0a2ce49b39321057c94427933de81663f680237a398e9929ba3 -size 442729 +oid sha256:2adfc04e0f7999ba861bf931b853f068067387558e81464e99caba1c2445a3a7 +size 444811 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png new file mode 100644 index 0000000000..057e117409 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_18_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0487a6dbc3a2f3bfb79a709c782fb692ef93f37607b4483095ce76f08954580e +size 396582 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png new file mode 100644 index 0000000000..bc7a7cc257 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_19_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29833e4103ecf4bd3e1c5da384d3bcc20031073a14261971825e97bc9f1dad23 +size 397593 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png new file mode 100644 index 0000000000..aa8d934627 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_20_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b544362587868c37edc424b675c6758e7ffcff359fa12c1cfcb874a0502e25de +size 397284 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png new file mode 100644 index 0000000000..26758e047f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_21_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51e183ca6d518d803471ad4eed0ee932397c32a4c1ffb064714b39f13ea2003f +size 396825 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png new file mode 100644 index 0000000000..7f34e6d53c --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_22_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b6623e0e784a93d6a3aa220b620efe7d1f9e040aedac7f34d01b24262fe101b +size 401770 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png index 167467d515..7d1ba874a3 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3bd4a96daaa24c01b7d0007fdd14460dc80c65c13d0ccc7a887b04fd90e9fa99 -size 396805 +oid sha256:d56f08f1c37575de90a67ebfeadaf1c891c9ac9e4925af7d048922df9fec5aa9 +size 396815 diff --git a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png index c44162b0ff..52f17795bb 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.mediaviewer.impl.viewer_MediaViewerView_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c0249f33aca3e50713c87a3826e71985991f0996998132c42a374c6169800023 -size 130728 +oid sha256:e3a148746b4f7428688a634f2b1299f0393bf669a665c94fa9af12d7839e72a0 +size 130834 diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 03ada90c4b..6ea495439e 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -331,6 +331,7 @@ "screen_blocked_users_.*", "full_screen_intent_banner_.*", "troubleshoot_notifications_entry_point_.*", + "theme\\..*", "screen\\.labs\\..*" ] },