From a96c146d30e5ae757fb4cf87cd95787ee152670e Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Mon, 23 Mar 2026 15:26:16 +0400 Subject: [PATCH 01/44] Introduce "Black" theme and refactor theme handling * Add `Theme.Black` to the `Theme` enum and update `isDark()` to include it. * Refactor `ElementTheme` to accept a `Theme` object instead of a `darkTheme` boolean, allowing for more specific color mapping (e.g., setting `bgCanvasDefault` to `Color.Black` for the Black theme). * Update `AdvancedSettingsPresenter` and `AdvancedSettingsState` to include "Black" as a user-selectable theme option. * Adjust `ElementThemeApp` and `MaterialTextPreview` to handle the expanded theme selection. * Add `ElementPreviewBlack` and update existing preview components to support the new theme. * Update Konsist tests to ensure `@PreviewsDayNight` annotated functions don't have "BlackPreview" suffix. --- .../impl/timeline/protection/ProtectedView.kt | 3 ++- .../advanced/AdvancedSettingsPresenter.kt | 2 ++ .../impl/advanced/AdvancedSettingsState.kt | 7 ++++++ .../impl/advanced/AdvancedSettingsView.kt | 6 +++++ .../compound/previews/CompoundIconsPreview.kt | 3 ++- .../previews/SemanticColorsPreview.kt | 5 ++-- .../android/compound/theme/AvatarColors.kt | 2 +- .../android/compound/theme/ElementTheme.kt | 23 ++++++++++++------ .../compound/theme/ForcedDarkElementTheme.kt | 2 +- .../compound/theme/MaterialTextPreview.kt | 14 +++++++---- .../compound/theme/MaterialThemeColors.kt | 16 +++++++++++-- .../element/android/compound/theme/Theme.kt | 3 ++- .../compound/screenshot/CompoundIconTest.kt | 3 ++- .../screenshot/MaterialYouThemeTest.kt | 3 ++- .../designsystem/atomic/pages/SunsetPage.kt | 3 ++- .../designsystem/preview/ElementPreview.kt | 5 ++-- .../preview/ElementPreviewBlack.kt | 24 +++++++++++++++++++ .../preview/ElementPreviewDark.kt | 3 ++- .../preview/ElementPreviewLight.kt | 3 ++- .../preview/ElementThemedPreview.kt | 9 +++---- .../designsystem/theme/ElementThemeApp.kt | 5 ++-- .../src/main/res/values/temporary.xml | 10 ++++++++ .../tests/konsist/KonsistPreviewTest.kt | 3 ++- 23 files changed, 121 insertions(+), 36 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewBlack.kt create mode 100644 libraries/ui-strings/src/main/res/values/temporary.xml diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedView.kt index de55735b76..2dbe47e9e4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/protection/ProtectedView.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.semantics.Role 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.theme.Theme import io.element.android.features.messages.impl.timeline.components.event.TimelineItemAspectRatioBox import io.element.android.libraries.designsystem.components.blurhash.blurHashBackground import io.element.android.libraries.designsystem.preview.ElementPreview @@ -49,7 +50,7 @@ fun ProtectedView( .background(Color(0x99000000)), contentAlignment = Alignment.Center, ) { - ElementTheme(darkTheme = false, applySystemBarsUpdate = false) { + ElementTheme(theme = Theme.Light, applySystemBarsUpdate = false) { // Not using a button to be able to have correct size Text( modifier = Modifier 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 c2871e0be8..5f95806469 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 @@ -56,6 +56,7 @@ class AdvancedSettingsPresenter( when (theme.value) { Theme.System -> ThemeOption.System Theme.Dark -> ThemeOption.Dark + Theme.Black -> ThemeOption.Black Theme.Light -> ThemeOption.Light } } @@ -98,6 +99,7 @@ class AdvancedSettingsPresenter( when (event.theme) { ThemeOption.System -> appPreferencesStore.setTheme(Theme.System.name) ThemeOption.Dark -> appPreferencesStore.setTheme(Theme.Dark.name) + ThemeOption.Black -> appPreferencesStore.setTheme(Theme.Black.name) ThemeOption.Light -> appPreferencesStore.setTheme(Theme.Light.name) } } 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 6eb7414a29..be443e905b 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 @@ -48,6 +48,13 @@ enum class ThemeOption : DropdownOption { @ReadOnlyComposable override fun getText(): String = stringResource(CommonStrings.common_dark) }, + + Black { + @Composable + @ReadOnlyComposable + override fun getText(): String = stringResource(CommonStrings.common_black) + }, + Light { @Composable @ReadOnlyComposable 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 c2b51973d0..f8f1faebbd 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 @@ -29,6 +29,7 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewBlack import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -324,6 +325,11 @@ internal fun AdvancedSettingsViewLightPreview(@PreviewParameter(AdvancedSettings internal fun AdvancedSettingsViewDarkPreview(@PreviewParameter(AdvancedSettingsStateProvider::class) state: AdvancedSettingsState) = ElementPreviewDark { ContentToPreview(state) } +@PreviewWithLargeHeight +@Composable +internal fun AdvancedSettingsViewBlackPreview(@PreviewParameter(AdvancedSettingsStateProvider::class) state: AdvancedSettingsState) = + ElementPreviewBlack { ContentToPreview(state) } + @ExcludeFromCoverage @Composable private fun ContentToPreview(state: AdvancedSettingsState) { diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/previews/CompoundIconsPreview.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/previews/CompoundIconsPreview.kt index 236e3627f4..7b1219a9f9 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/previews/CompoundIconsPreview.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/previews/CompoundIconsPreview.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.Theme import io.element.android.compound.tokens.generated.CompoundIcons import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -62,7 +63,7 @@ internal fun IconsCompoundPreviewRtl() = ElementTheme { @Preview(widthDp = 730, heightDp = 1920) @Composable -internal fun IconsCompoundPreviewDark() = ElementTheme(darkTheme = true) { +internal fun IconsCompoundPreviewDark() = ElementTheme(theme = Theme.Dark) { IconsCompoundPreview() } diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/previews/SemanticColorsPreview.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/previews/SemanticColorsPreview.kt index 3f5fb42149..735f8f495d 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/previews/SemanticColorsPreview.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/previews/SemanticColorsPreview.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.Theme import io.element.android.compound.tokens.generated.compoundColorsHcDark import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentMapOf @@ -65,7 +66,7 @@ internal fun CompoundSemanticColorsLightHc() = ElementTheme( @Preview(heightDp = 2000) @Composable -internal fun CompoundSemanticColorsDark() = ElementTheme(darkTheme = true) { +internal fun CompoundSemanticColorsDark() = ElementTheme(theme = Theme.Dark) { Surface { Column( modifier = Modifier.padding(16.dp), @@ -85,7 +86,7 @@ internal fun CompoundSemanticColorsDark() = ElementTheme(darkTheme = true) { @Preview(heightDp = 2000) @Composable internal fun CompoundSemanticColorsDarkHc() = ElementTheme( - darkTheme = true, + theme = Theme.Dark, compoundDark = compoundColorsHcDark, ) { Surface { diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/AvatarColors.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/AvatarColors.kt index 763f422a00..8d3e495332 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/AvatarColors.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/AvatarColors.kt @@ -65,7 +65,7 @@ internal fun AvatarColorsPreviewLight() { @Preview @Composable internal fun AvatarColorsPreviewDark() { - ElementTheme(darkTheme = true) { + ElementTheme(theme = Theme.Dark) { val chunks = avatarColors().chunked(4) Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { for (chunk in chunks) { diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ElementTheme.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ElementTheme.kt index bb2ae2b62e..ac83365658 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ElementTheme.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ElementTheme.kt @@ -77,10 +77,10 @@ internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLigh /** * Sets up the theme for the application, or a part of it. * - * @param darkTheme whether to use the dark theme or not. If `true`, the dark theme will be used. + * @param theme the [Theme] to use. Defaults to [Theme.Dark] or [Theme.Light] based on the system setting. * @param applySystemBarsUpdate whether to update the system bars color scheme or not when the theme changes. It's `true` by default. * This is specially useful when you want to apply an alternate theme to a part of the app but don't want it to affect the system bars. - * @param lightStatusBar whether to use a light status bar color scheme or not. By default, it's the opposite of [darkTheme]. + * @param lightStatusBar whether to use a light status bar color scheme or not. By default, it's `true` for light themes and `false` for dark ones. * @param dynamicColor whether to enable MaterialYou or not. It's `false` by default. * @param compoundLight the [SemanticColors] to use in light theme. * @param compoundDark the [SemanticColors] to use in dark theme. @@ -91,9 +91,9 @@ internal val LocalCompoundColors = staticCompositionLocalOf { compoundColorsLigh */ @Composable fun ElementTheme( - darkTheme: Boolean = isSystemInDarkTheme(), + theme: Theme = if (isSystemInDarkTheme()) Theme.Dark else Theme.Light, applySystemBarsUpdate: Boolean = true, - lightStatusBar: Boolean = !darkTheme, + lightStatusBar: Boolean = !theme.isDark(), // true to enable MaterialYou dynamicColor: Boolean = false, compoundLight: SemanticColors = compoundColorsLight, @@ -103,8 +103,13 @@ fun ElementTheme( typography: Typography = compoundTypography, content: @Composable () -> Unit, ) { + val darkTheme = theme.isDark() val currentCompoundColor = when { - darkTheme -> compoundDark + darkTheme -> if (theme == Theme.Black) { + compoundDark.copy(bgCanvasDefault = Color.Black) + } else { + compoundDark + } else -> compoundLight } @@ -113,7 +118,11 @@ fun ElementTheme( val context = LocalContext.current if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) } - darkTheme -> materialColorsDark + darkTheme -> if (theme == Theme.Black) { + currentCompoundColor.toMaterialColorScheme() + } else { + materialColorsDark + } else -> materialColorsLight } @@ -130,7 +139,7 @@ fun ElementTheme( if (applySystemBarsUpdate) { val activity = LocalActivity.current as? ComponentActivity - LaunchedEffect(statusBarColorScheme, darkTheme, lightStatusBar) { + LaunchedEffect(statusBarColorScheme, theme, lightStatusBar) { activity?.enableEdgeToEdge( // For Status bar use the background color of the app statusBarStyle = SystemBarStyle.auto( diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ForcedDarkElementTheme.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ForcedDarkElementTheme.kt index 272245f199..8f9d2bdf0c 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ForcedDarkElementTheme.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/ForcedDarkElementTheme.kt @@ -51,7 +51,7 @@ fun ForcedDarkElementTheme( } } ElementTheme( - darkTheme = true, + theme = Theme.Dark, compoundLight = colors.light, compoundDark = colors.dark, lightStatusBar = lightStatusBar, diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialTextPreview.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialTextPreview.kt index 792c7fbabf..27e874c141 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialTextPreview.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialTextPreview.kt @@ -36,11 +36,15 @@ internal fun MaterialTextPreview() = Row( ) { MaterialPreview( modifier = Modifier.weight(1f), - darkTheme = false, + theme = Theme.Light, ) MaterialPreview( modifier = Modifier.weight(1f), - darkTheme = true, + theme = Theme.Dark, + ) + MaterialPreview( + modifier = Modifier.weight(1f), + theme = Theme.Black, ) } @@ -52,7 +56,7 @@ private data class Model( @Composable private fun MaterialPreview( - darkTheme: Boolean, + theme: Theme, modifier: Modifier = Modifier, ) = Column(modifier = modifier) { Text( @@ -60,13 +64,13 @@ private fun MaterialPreview( .fillMaxWidth() .padding(8.dp), textAlign = TextAlign.Center, - text = if (darkTheme) "Dark" else "Light", + text = theme.name, color = Color.Black, fontSize = 18.sp, fontWeight = FontWeight.Bold, ) ElementTheme( - darkTheme = darkTheme, + theme = theme, ) { Column( modifier = Modifier.fillMaxSize() diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialThemeColors.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialThemeColors.kt index c2a923e926..c283780295 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialThemeColors.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/MaterialThemeColors.kt @@ -50,7 +50,7 @@ internal fun ColorsSchemeLightHcPreview() = ElementTheme( @Preview(heightDp = 1200) @Composable internal fun ColorsSchemeDarkPreview() = ElementTheme( - darkTheme = true, + theme = Theme.Dark, ) { ColorsSchemePreview( Color.White, @@ -62,7 +62,7 @@ internal fun ColorsSchemeDarkPreview() = ElementTheme( @Preview(heightDp = 1200) @Composable internal fun ColorsSchemeDarkHcPreview() = ElementTheme( - darkTheme = true, + theme = Theme.Dark, compoundDark = compoundColorsHcDark, ) { ColorsSchemePreview( @@ -71,3 +71,15 @@ internal fun ColorsSchemeDarkHcPreview() = ElementTheme( ElementTheme.materialColors, ) } + +@Preview(heightDp = 1200) +@Composable +internal fun ColorsSchemeBlackPreview() = ElementTheme( + theme = Theme.Black +) { + ColorsSchemePreview( + Color.White, + Color.Black, + ElementTheme.materialColors, + ) +} diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt index 131b14430c..fd00abb4f4 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.map enum class Theme { System, Dark, + Black, Light, } @@ -23,7 +24,7 @@ enum class Theme { fun Theme.isDark(): Boolean { return when (this) { Theme.System -> isSystemInDarkTheme() - Theme.Dark -> true + Theme.Dark, Theme.Black -> true Theme.Light -> false } } diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt index 6e15233013..3e8ce06cdb 100644 --- a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/CompoundIconTest.kt @@ -19,6 +19,7 @@ import io.element.android.compound.previews.IconsCompoundPreviewRtl import io.element.android.compound.previews.IconsPreview import io.element.android.compound.screenshot.utils.screenshotFile import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.Theme import io.element.android.compound.tokens.generated.CompoundIcons import kotlinx.collections.immutable.toImmutableList import org.junit.Test @@ -56,7 +57,7 @@ class CompoundIconTest { val content: List<@Composable ColumnScope.() -> Unit> = CompoundIcons.all.map { @Composable { Icon(imageVector = it, contentDescription = null) } } - ElementTheme(darkTheme = true) { + ElementTheme(theme = Theme.Dark) { IconsPreview( title = "Compound Vector Icons", content = content.toImmutableList() diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt index 2fe3167199..dcbbc9d4ac 100644 --- a/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/screenshot/MaterialYouThemeTest.kt @@ -24,6 +24,7 @@ import com.github.takahirom.roborazzi.captureRoboImage import io.element.android.compound.previews.ColorsSchemePreview import io.element.android.compound.screenshot.utils.screenshotFile import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.Theme import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config @@ -51,7 +52,7 @@ class MaterialYouThemeTest { } } captureRoboImage(file = screenshotFile("MaterialYou Theme - Dark.png")) { - ElementTheme(dynamicColor = true, darkTheme = true) { + ElementTheme(dynamicColor = true, theme = Theme.Dark) { Surface { Column( modifier = Modifier.padding(16.dp), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt index c2ee9800db..0ff1533ea0 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/pages/SunsetPage.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import io.element.android.compound.annotations.CoreColorToken import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.Theme import io.element.android.compound.tokens.generated.internal.DarkColorTokens import io.element.android.compound.tokens.generated.internal.LightColorTokens import io.element.android.libraries.designsystem.R @@ -50,7 +51,7 @@ fun SunsetPage( ) { ElementTheme( // Always use the opposite value of the current theme - darkTheme = ElementTheme.isLightTheme, + theme = if (ElementTheme.isLightTheme) Theme.Dark else Theme.Light, applySystemBarsUpdate = false, ) { Box( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt index b0ef41e154..e4030a77ea 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt @@ -19,6 +19,7 @@ import coil3.asImage import coil3.compose.AsyncImagePreviewHandler import coil3.compose.LocalAsyncImagePreviewHandler import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.theme.Theme import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.utils.CommonDrawables @@ -26,7 +27,7 @@ import io.element.android.libraries.designsystem.utils.CommonDrawables @Composable @Suppress("ModifierMissing") fun ElementPreview( - darkTheme: Boolean = isSystemInDarkTheme(), + theme: Theme = if (isSystemInDarkTheme()) Theme.Dark else Theme.Light, showBackground: Boolean = true, @DrawableRes drawableFallbackForImages: Int = CommonDrawables.sample_background, @@ -38,7 +39,7 @@ fun ElementPreview( ResourcesCompat.getDrawable(context.resources, drawableFallbackForImages, null)!!.asImage() } ) { - ElementTheme(darkTheme = darkTheme) { + ElementTheme(theme = theme) { if (showBackground) { // If we have a proper contentColor applied we need a Surface instead of a Box Surface(content = content) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewBlack.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewBlack.kt new file mode 100644 index 0000000000..c10b4272e2 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewBlack.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Element Creations Ltd. + * Copyright 2023-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.preview + +import androidx.compose.runtime.Composable +import io.element.android.compound.theme.Theme + +@Composable +fun ElementPreviewBlack( + showBackground: Boolean = true, + content: @Composable () -> Unit +) { + ElementPreview( + theme = Theme.Black, + showBackground = showBackground, + content = content + ) +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt index c054b318f3..ec7b485d47 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.designsystem.preview import androidx.compose.runtime.Composable +import io.element.android.compound.theme.Theme @Composable fun ElementPreviewDark( @@ -16,7 +17,7 @@ fun ElementPreviewDark( content: @Composable () -> Unit ) { ElementPreview( - darkTheme = true, + theme = Theme.Dark, showBackground = showBackground, content = content ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt index 1c2bdf3cef..1d0df3dd10 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.designsystem.preview import androidx.compose.runtime.Composable +import io.element.android.compound.theme.Theme @Composable fun ElementPreviewLight( @@ -16,7 +17,7 @@ fun ElementPreviewLight( content: @Composable () -> Unit ) { ElementPreview( - darkTheme = false, + theme = Theme.Light, showBackground = showBackground, content = content ) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt index 7b29757843..a0bd489f8c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.Theme import io.element.android.libraries.designsystem.utils.CommonDrawables @Composable @@ -40,14 +41,14 @@ fun ElementThemedPreview( if (vertical) { Column { ElementPreview( - darkTheme = false, + theme = Theme.Light, showBackground = showBackground, drawableFallbackForImages = drawableFallbackForImages, content = content, ) Spacer(modifier = Modifier.height(4.dp)) ElementPreview( - darkTheme = true, + theme = Theme.Dark, showBackground = showBackground, drawableFallbackForImages = drawableFallbackForImages, content = content @@ -56,14 +57,14 @@ fun ElementThemedPreview( } else { Row { ElementPreview( - darkTheme = false, + theme = Theme.Light, showBackground = showBackground, drawableFallbackForImages = drawableFallbackForImages, content = content, ) Spacer(modifier = Modifier.width(4.dp)) ElementPreview( - darkTheme = true, + theme = Theme.Dark, showBackground = showBackground, drawableFallbackForImages = drawableFallbackForImages, content = content diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt index 7aa0ab79b9..a7bd12bc13 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt @@ -18,7 +18,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.staticCompositionLocalOf import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.Theme -import io.element.android.compound.theme.isDark import io.element.android.compound.theme.mapToTheme import io.element.android.compound.tokens.generated.SemanticColors import io.element.android.libraries.core.meta.BuildMeta @@ -68,7 +67,7 @@ fun ElementThemeApp( when (theme) { Theme.System -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM Theme.Light -> AppCompatDelegate.MODE_NIGHT_NO - Theme.Dark -> AppCompatDelegate.MODE_NIGHT_YES + Theme.Dark, Theme.Black -> AppCompatDelegate.MODE_NIGHT_YES } ) } @@ -76,7 +75,7 @@ fun ElementThemeApp( LocalBuildMeta provides buildMeta, ) { ElementTheme( - darkTheme = theme.isDark(), + theme = theme, content = content, compoundLight = compoundLight, compoundDark = compoundDark, diff --git a/libraries/ui-strings/src/main/res/values/temporary.xml b/libraries/ui-strings/src/main/res/values/temporary.xml new file mode 100644 index 0000000000..ba6c431d8b --- /dev/null +++ b/libraries/ui-strings/src/main/res/values/temporary.xml @@ -0,0 +1,10 @@ + + + + "Black" + diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt index f4d02095fb..47877f3a95 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt @@ -30,7 +30,8 @@ class KonsistPreviewTest { .assertTrue { it.hasNameEndingWith("Preview") && it.hasNameEndingWith("LightPreview").not() && - it.hasNameEndingWith("DarkPreview").not() + it.hasNameEndingWith("DarkPreview").not() && + it.hasNameEndingWith("BlackPreview").not() } } From cea003a929bafc933335700272bd6c26dc3a4c60 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Mon, 23 Mar 2026 12:23:50 +0000 Subject: [PATCH 02/44] Update screenshots --- libraries/compound/screenshots/MaterialText Colors.png | 4 ++-- ...eferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png | 3 +++ ...eferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png | 3 +++ 10 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png diff --git a/libraries/compound/screenshots/MaterialText Colors.png b/libraries/compound/screenshots/MaterialText Colors.png index f8f77ccca2..1273aee01e 100644 --- a/libraries/compound/screenshots/MaterialText Colors.png +++ b/libraries/compound/screenshots/MaterialText Colors.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4be10c3bb9900d27a3b406eca0cb902b0ff9cdf90e8e3cf1ae7760aa7c5d47d9 -size 377446 +oid sha256:1f1a277e76d351f48ae0041e082525422604fbf41d77fe078112349855dd3d2e +size 453512 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 new file mode 100644 index 0000000000..da80c7af53 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:645a7fb89953ff6e72119a105ac966cabaf8ca6a68f3023534301e3471b942f2 +size 49262 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 new file mode 100644 index 0000000000..6aa030a83a --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea52fd146c53b690c1273b090c6b66701a8f40d80eb1dc693898c3dbf8b24def +size 49115 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 new file mode 100644 index 0000000000..a31686aaad --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf3e4ffa06a77fbaa9dc9985274d6b1324fb023f5eeb2b9d229af0854b41e236 +size 49095 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 new file mode 100644 index 0000000000..421367fee7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f68a09667dc19c935decb5b640bed2410dd16ae88c0d0ab6ca410225e48a87da +size 49111 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 new file mode 100644 index 0000000000..fbcd0538aa --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5defae968cccb0e78ceff23912a364cf72f9ed61ea6ae3cc9770af9c39b05f9d +size 49035 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 new file mode 100644 index 0000000000..7a3e1e9682 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c590f67875f9bdc460ab82b59cd3c9e11147bfadc59028552071b64fd440f211 +size 49259 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 new file mode 100644 index 0000000000..9c788eb3ab --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d48af05c854a8f313f10aaa774e4268756dcf7e0c2bea0e138dc6cd84137673 +size 48995 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 new file mode 100644 index 0000000000..9d375b0b74 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1507eeffcfacfcf6c84494f09d89ef3478748ae31f8fee4a9922e4188ccb454 +size 48563 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 new file mode 100644 index 0000000000..fac0ba3da5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4146fd85887aca1a0a65ef559976c1436d1fc2b0de522295f27bfaef1d904ea4 +size 55410 From a22c9871e3d271d8044d7545330f5a7b00d8163f Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 17 Mar 2026 12:28:44 +0100 Subject: [PATCH 03/44] Map sdk timeline item for LiveLocation --- .../event/TimelineItemLocationView.kt | 2 +- .../event/TimelineItemContentFactory.kt | 1 - .../TimelineItemContentMessageFactory.kt | 1 - .../event/TimelineItemLocationContent.kt | 1 - .../TimelineItemLocationContentProvider.kt | 4 ++-- .../api/timeline/item/event/EventContent.kt | 1 - .../item/event/TimelineEventContentMapper.kt | 21 +++++++++++++++++-- 7 files changed, 22 insertions(+), 9 deletions(-) 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 592b95a337..576f7bd2d5 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 @@ -33,7 +33,7 @@ fun TimelineItemLocationView( lat = content.location.lat, lon = content.location.lon, zoom = 15.0, - contentDescription = content.body + contentDescription = content.description ) } 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 2b5c0fa98a..85fa8a0dc1 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 @@ -105,7 +105,6 @@ class TimelineItemContentFactory( }.lastOrNull() if (lastKnownLocation != null) { TimelineItemLocationContent( - body = itemContent.body.trimEnd(), description = itemContent.description?.trimEnd(), assetType = itemContent.assetType, senderId = sender, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt index 723ab6feac..a5e2f922ad 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt @@ -150,7 +150,6 @@ class TimelineItemContentMessageFactory( ) } else { TimelineItemLocationContent( - body = body, location = location, description = messageType.description, senderId = senderId, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt index aa9fb6b71e..f90dcbef03 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt @@ -19,7 +19,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.getAvatarUrl import io.element.android.libraries.matrix.api.timeline.item.event.getDisplayName data class TimelineItemLocationContent( - val body: String, val senderId: UserId, val senderProfile: ProfileDetails, val location: Location, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt index 362e9b4cda..5c87c5c538 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt @@ -24,12 +24,11 @@ open class TimelineItemLocationContentProvider : PreviewParameterProvider { - // Live location messages are a special kind of message that we want to treat as unknown content for now - UnknownContent + LiveLocationContent( + isLive = kind.content.isLive, + description = kind.content.description, + timeout = kind.content.timeoutMs.toLong(), + assetType = kind.content.assetType.into(), + locations = kind.content.locations.map { location -> location.map() } + ) } is MsgLikeKind.Other -> UnknownContent } @@ -260,3 +269,11 @@ private fun RustEncryptedMessage.map(): UnableToDecryptContent.Data { RustEncryptedMessage.Unknown -> UnableToDecryptContent.Data.Unknown } } + +private fun BeaconInfo.map(): LiveLocationInfo { + return LiveLocationInfo( + description = description, + geoUri = geoUri, + timestamp = ts.toLong(), + ) +} From b082f59f9c00bd0b2c93c833df0fceaac2190ed6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 24 Mar 2026 16:38:12 +0100 Subject: [PATCH 04/44] Start implementing LLS timeline item --- .../features/location/api/StaticMapView.kt | 151 ++++++++++++------ .../api/internal/StaticMapPlaceholder.kt | 20 +-- .../src/main/res/drawable-night/stale_map.png | Bin 0 -> 2663 bytes .../api/src/main/res/drawable/stale_map.png | Bin 0 -> 3310 bytes .../messages/impl/timeline/TimelineEvent.kt | 2 + .../impl/timeline/TimelinePresenter.kt | 1 + .../components/TimelineItemEventRow.kt | 55 ++++--- .../timeline/components/TimestampPosition.kt | 7 +- .../event/TimelineItemEventContentView.kt | 1 + .../event/TimelineItemLocationView.kt | 131 ++++++++++++++- .../event/TimelineItemContentFactory.kt | 26 +-- .../TimelineItemContentMessageFactory.kt | 3 +- .../event/TimelineItemEventContentProvider.kt | 2 +- .../event/TimelineItemLocationContent.kt | 31 +++- .../TimelineItemLocationContentProvider.kt | 46 ++++-- .../TimelineItemContentMessageFactoryTest.kt | 1 - 16 files changed, 356 insertions(+), 121 deletions(-) create mode 100644 features/location/api/src/main/res/drawable-night/stale_map.png create mode 100644 features/location/api/src/main/res/drawable/stale_map.png diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt index 0657bae634..3ee0af35af 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt @@ -9,7 +9,9 @@ package io.element.android.features.location.api import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.BoxWithConstraintsScope import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -22,6 +24,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import coil3.Extras import coil3.compose.AsyncImagePainter @@ -38,68 +42,131 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight /** * Shows a static map image downloaded via a third party service's static maps API. + * + * Handles 4 distinct cases: + * 1. Stale location (pinVariant is StaleLocation) - shows stale map with stale pin, no fetching + * 2. Null location - shows blurred placeholder, no pin, no loading + * 3. Loading (location != null, fetching) - shows blurred placeholder with loading indicator + * 4. Success (location != null, loaded) - shows actual map with pin */ @Composable fun StaticMapView( - lat: Double, - lon: Double, + location: Location?, zoom: Double, pinVariant: PinVariant, contentDescription: String?, modifier: Modifier = Modifier, darkMode: Boolean = !ElementTheme.isLightTheme, ) { - // Using BoxWithConstraints to: - // 1) Size the inner Image to the same Dp size of the outer BoxWithConstraints. - // 2) Request the static map image of the exact required size in Px to fill the AsyncImage. BoxWithConstraints( modifier = modifier, contentAlignment = Alignment.Center ) { - val context = LocalContext.current - var retryHash by remember { mutableIntStateOf(0) } - val builder = remember { StaticMapUrlBuilder() } - val painter = rememberAsyncImagePainter( - model = if (constraints.isZero) { - // Avoid building a URL if any of the size constraints is zero (else it will thrown an exception). - null - } else { - ImageRequest.Builder(context) - .data( - builder.build( - lat = lat, - lon = lon, - zoom = zoom, - darkMode = darkMode, - width = constraints.maxWidth, - height = constraints.maxHeight, - density = LocalDensity.current.density, - ) - ) - .size(width = constraints.maxWidth, height = constraints.maxHeight) - .apply { - extras.set(Extras.Key("retry_hash"), retryHash).build() - } - .build() + // Case 1: Stale location - show stale map with stale pin, no fetching + when { + pinVariant is PinVariant.StaleLocation -> { + StaleMapContent( + pinVariant = pinVariant, + contentDescription = contentDescription, + width = maxWidth, + height = maxHeight, + ) } - ) + // Case 2: Null location - show blurred placeholder, no pin, no loading + location == null -> { + StaticMapPlaceholder( + painter = painterResource(R.drawable.blurred_map), + canReload = false, + contentDescription = contentDescription, + width = maxWidth, + height = maxHeight, + onLoadMapClick = {} + ) + } + // Cases 3 & 4: Non-null location - fetch map + else -> LoadableMapContent( + location = location, + zoom = zoom, + pinVariant = pinVariant, + contentDescription = contentDescription, + darkMode = darkMode, + ) + } + } +} - val collectedState = painter.state.collectAsState() - if (collectedState.value is AsyncImagePainter.State.Success) { +@Composable +private fun BoxWithConstraintsScope.StaleMapContent( + pinVariant: PinVariant, + contentDescription: String?, + width: Dp, + height: Dp, +) { + Box(contentAlignment = Alignment.Center) { + Image( + painter = painterResource(R.drawable.stale_map), + contentDescription = contentDescription, + contentScale = ContentScale.FillBounds, + modifier = Modifier.size(width = width, height = height) + ) + LocationPin(variant = pinVariant, modifier = Modifier.centerBottomEdge(this@StaleMapContent)) + } +} + +@Composable +private fun BoxWithConstraintsScope.LoadableMapContent( + location: Location, + zoom: Double, + pinVariant: PinVariant, + contentDescription: String?, + darkMode: Boolean, +) { + val context = LocalContext.current + var retryHash by remember { mutableIntStateOf(0) } + val builder = remember { StaticMapUrlBuilder() } + + val painter = rememberAsyncImagePainter( + model = if (constraints.isZero) { + // Avoid building a URL if any of the size constraints is zero + null + } else { + ImageRequest.Builder(context) + .data( + builder.build( + lat = location.lat, + lon = location.lon, + zoom = zoom, + darkMode = darkMode, + width = constraints.maxWidth, + height = constraints.maxHeight, + density = LocalDensity.current.density, + ) + ) + .size(width = constraints.maxWidth, height = constraints.maxHeight) + .apply { + extras.set(Extras.Key("retry_hash"), retryHash).build() + } + .build() + } + ) + + val state by painter.state.collectAsState() + when (state) { + is AsyncImagePainter.State.Success -> { Image( painter = painter, contentDescription = contentDescription, modifier = Modifier.size(width = maxWidth, height = maxHeight), // The returned image can be smaller than the requested size due to the static maps API having - // a max width and height of 2048 px. See buildStaticMapsApiUrl() for more details. - // We apply ContentScale.Fit to scale the image to fill the AsyncImage should this be the case. + // a max width and height of 2048 px. We apply ContentScale.Fit to handle this. contentScale = ContentScale.Fit, ) LocationPin(variant = pinVariant, modifier = Modifier.centerBottomEdge(this)) - } else { + } + else -> { StaticMapPlaceholder( - showProgress = collectedState.value.isLoading(), - canReload = builder.isServiceAvailable(), + painter = painterResource(R.drawable.blurred_map), + canReload = builder.isServiceAvailable() && state is AsyncImagePainter.State.Error, contentDescription = contentDescription, width = maxWidth, height = maxHeight, @@ -109,17 +176,11 @@ fun StaticMapView( } } -private fun AsyncImagePainter.State.isLoading(): Boolean { - return this is AsyncImagePainter.State.Empty || - this is AsyncImagePainter.State.Loading -} - @PreviewsDayNight @Composable internal fun StaticMapViewPreview() = ElementPreview { StaticMapView( - lat = 0.0, - lon = 0.0, + location = Location(0.0, 0.0), zoom = 0.0, contentDescription = null, pinVariant = PinVariant.PinnedLocation, diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt index 81b80c8dc3..735a25fef9 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt @@ -18,6 +18,7 @@ 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.graphics.painter.Painter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -34,7 +35,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Composable internal fun StaticMapPlaceholder( - showProgress: Boolean, + painter: Painter, canReload: Boolean, contentDescription: String?, width: Dp, @@ -46,17 +47,15 @@ internal fun StaticMapPlaceholder( contentAlignment = Alignment.Center, modifier = modifier .size(width = width, height = height) - .then(if (showProgress) Modifier else Modifier.clickable(onClick = onLoadMapClick)) + .clickable(enabled = canReload, onClick = onLoadMapClick) ) { Image( - painter = painterResource(id = R.drawable.blurred_map), + painter = painter, contentDescription = contentDescription, contentScale = ContentScale.FillBounds, modifier = Modifier.size(width = width, height = height) ) - if (showProgress) { - CircularProgressIndicator() - } else if (canReload) { + if (canReload) { Column( horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -77,13 +76,10 @@ internal fun StaticMapPlaceholderPreview() = ElementPreview { modifier = Modifier.padding(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - listOf( - true to false, - false to true, - false to false, - ).forEach { (showProgress, canReload) -> + listOf(false, true) + .forEach { canReload -> StaticMapPlaceholder( - showProgress = showProgress, + painter = painterResource(R.drawable.blurred_map), canReload = canReload, contentDescription = null, width = 400.dp, diff --git a/features/location/api/src/main/res/drawable-night/stale_map.png b/features/location/api/src/main/res/drawable-night/stale_map.png new file mode 100644 index 0000000000000000000000000000000000000000..9e367592037fb72087f0c58d5bd89b01d5ed04af GIT binary patch literal 2663 zcmXX|d0Z3M77mRiDuyULg+_FI;(`JSHdRD2EMf++P(TD)c7qtL$RY|&89>nhB^Z_} zQkEEoN&wm1P>{tRVo>{p=&-neL_i@y7G)Gigm=gH{+PMv+ji#jwKgwxN*Xfz#t>eHhAm2U_pwT^ip4z$WgMk7F( zchKI&o<^&Y=*$Fv3v}J+T|Uu!!$YHEf};-5c!vsB$w=L4u$yB+O4W3}G)>io1E zSuRqw-gzCQyDqb=%%gK|ZeZ2cyGBR!o*k^!@4DCgtgoOTrtfoBkq0WZ!gol*jjCC* zGa6~m>Y~Y5zeUL{uez%Ozoq4A?+S^Di5Ze^4s84vgTeTg_InXa5oBQ!KRffYUtpj? zdwcs(BCUEY88I{4JjYCVF!15Sd6Fg`3A1{@az$zD2x}uPLaQh1Zp3^rWd0K|4`*aF z4vKclS*yZ!>mqh2?U1w3syG08IFv=w^fG25=CLzA#RdEm`n{SyoSUm!oPH)=afYOk z2M$}E5~9OlYI@4UK?-h4F$#GJdQVcGYCgyCc_n=Uvw(mAIV%WBx*y`P za`l(Vb-3c=_{)cuGB`0*+uAI!Dc+oixvQ?jgRfs-iWLfr;6&{Q3M-DG@DOjDn4FjZ zJ~3zFBRmrZ>`*tzPCtCs>kJ8)v>%z#_^6Xe8vIVx9_a?*jOzO(wlp3vYOcFyyWJVR zUBUV?xS?O^qF}sjm{~(W5wl~S5{WO=uXx?O(t&J5%{)@ zC4&PrNeZ~XwJ#vFWFJONy89N58K$u3f0p6j2LzUhG2vg<yx{)3KNkM9*pY(db;azWTs|6-u+$xR@$Aj(v1Aa7j+Nftx`aJ?amA+bC<^j( z6WWnsYvMCP(> z>rHBv6Vq`eIAZO$2yw+gJ?gKON~QJjS3=ZS;8PZI6q9wIP&T|(se(V9Z*ZN02LQ-F9rrY0~XCKR>@e#}%5ikoGt4_ixQ}hgP(OS{bJAQyq7iiWjxW9+DkC z!_g!KetN_*u|9 z+>-rS25-a_WB(M`@GveY%No|W3ilCTR_XT&@s4IxV?0jf)u zZK{|Tr`p#!b=n?NwxM6kobU3uBvUz@19yYF+%F)YE`D@icD9jf7R2Ss`YfeW5*)K) z89H0WN(*dhoFabZluEpJ7drEdxiWZNcB)1JdqToo=k(M!q|;c)7WT+OV#&(S6Td)F z$Byl_;c{pPAuEIjwQn3idlbgt4 z;@TGWZ!&lWN5a>iSGMUBDhw8Gzb@v@$|bc#=0lyrJyTVul@nM1gdoV6W?*u%CaxjR z$dTJ17X3tqM+=3&`1$+as$wynbcrQzuO8&Y=`;oJL2q{@4=LcH{QW$-7LlpoLj?)< z#M)id9Uxm$;{_EIhVtl;3@-b=DBSmQCvs4_7CX64&dMW{_e(=L)#mCJFZ9}Mt|hx? zDG^)(|H1|R{mc$64umSutw3}{i~XUB{3ssXe*q!WlEIHlB@MQ8pz3V?&&5eA7`_DS z$t4Z0JFt@%qMzsI=l@AxjUx#}&3ohkrz6=7688T|-rNvaDU*;rBl!31;pK#T!OpLD zZT($fuU9WPmr*KV@Z@XMdH3s&vIkr`4j)At>-SWKq)Lg`+K%EYBOl21-g zaksFmMdWZJ4Eq5d=iQ;+PDMY)Y7;cq2~mNgTyjFqAJ}NYZc9I!fIfFXJqcM=g7iJN zXX?>+%)t~gwn8!zUFVHnzD&ooSaQi14c{#R5o_PR2zzPxurz!hG~{f-o^b9?{r}yW zR-xuM3!3XE=Go)Od(vuppuH*3ka}FFn z_A`1RkO>0SUn7w~pDnmXV(mId^mZT=nw+GxGs6`k(qz$o&SKvNcq)q7r)hZsdS^Jh zvR*0h3`nwe4A8XTV8-d>J%{dBAzLDSp->Unc-W>pIaL+J$=Fy$WX=GC>SkYb4TWwt z=?UG}Wnfz6HaL>iat8$Dg~s?6Wt;7%F)pP9%m@@KCDen*#5Nc6ZbXkVOml;Ba&lT@ zZThCyY+p7712mh*1Z<@H@a4_xK2QUN+TNvUdAxl%%!=|{ZEW))SoJ(708pZNb!rAi zN6kK6U4nwee$-2CtOmrI-ws+hRY+ow7WUeHe|V(5stpHTHyB`*67%kq#)I zf(>@t)V9aTzF+H4RAj3esct@a2hw)$a&@e9 H2s-s&mXafS literal 0 HcmV?d00001 diff --git a/features/location/api/src/main/res/drawable/stale_map.png b/features/location/api/src/main/res/drawable/stale_map.png new file mode 100644 index 0000000000000000000000000000000000000000..87fa0188c9f884944a463a24de5de4306d72c1f2 GIT binary patch literal 3310 zcmY*ceLPg__8&*36V0Sl(y(>uCTBF1T%ui~nO>OR-REuCU_mM=u zQ$GM>$r<~j_9Rj{syXMk6xig*{T`7np{FCG{K5lBjKDMJ{2r8Na7ZMrz=MwVt~|BT zeoc2hrY?WHXQ?=Ewc{n@qr`mu@kdhOenB%Y@yhS5NvU^D44>KV_%x|{9(b$E>gTy= zub$0M>uT=_+l{d=bL{>;vRiG2Dar3pi$1vk!?O)iZO_Ms=LZFr+%jg78rcN5?^`Gy z|1gLflP?Mxi$vr)@myC+s?84FDv9lR%RD&#rt2>1bleh5eR+z8BuxOvb9pWi==z;ro-6^) zh18-Q99A6^v-fJ22vx(?(l;d~`~P$3y1pieVCpm}e}>}+_eX8m22AhBKTUr}M0pID z40)3><}n&E@4ZE?@mbA(+s*|K$QD3*|0GGk1M7?c&QHx|QaJwWW(ne*yYm9;Ykb5$Qx8ysBtl@}G3BF$3Lg zqErsVBy4~sp1J=w=YqBT7kvrr-6x*ep1bo9@Jo2*I#FZ#^-9{BinvJAsTD&Z$dgD! z%VsJe-jz)i1tMP}k%yO55-;EWoJoIE$HBFKXlJzeJU@35(x`zio@yyYpTDbvE4zv* zyt0WwZV&Owwq4aCq6~4l58}2Y5%GL+%&5mtTMh~-lM?X(9bC;P+KsvmOC;j!#YjcW zU%>271`YH#>-fol!P~ore>Ftty{btWt{U2>U?vi8Q#{kRRRe8pQJW@C)$E6bKFU)( z%(B|~gjFHzob(oq)tK@1QZ#o^HFUVF^tD+kl1H^)54PkzMmeV-iLARWex38>ykyC6 zm-K7dk1|}Qz{~qX!au5Cxn5}PH4`J)@CTA3kV{= z+$DV-S`m%DQ9s=#8Z@<}kTVpGJhsx4Yk2!wzuAjq zzRH6?ua;P-1GyVqw4^ECk0^l@v0S52H`OMKsIF|AwPxMOZoP*RBuP0bg7r3Z{+ujI z7jv+>%5fTzP0cFwn-YV^0uXL{&Jryt)qo*^H{atcinrjhz~RkS%BkxcBo;=DA!Nkr zWU=Br68YuVpGHE~ZTY{2nt{0FG?~`)- zIF>C;ETGx5Ge2cfv2&c2dizVDOc+Y@$u=qqLU}`;aKBv zYuy{Gj(qgZoIDj{8;u+hQbMn7Br}X?m2glETz8?<6j!cfNq#+hImmy{h5pfu*Q0C* zUbTZdp2Ar0@2PNoyE%JNF_phJ^B3 zh~>o`A)~f%pe(Jno#0xx*B=AN%y1I1V_UP#oZfcxTgKPgY%>aIi;3qGi8g-L8mqBl zI4s)k>A3-H#?ZLWPu|c@%mI~V5++9?C7VJlsU5`3v~S+nmw_|Lv&?F|ysl;+qGMd5 zylJP0hGutHZOHK!4&BxS;~n@9xBA}7KkA*K7i(Vv;f`fh?Hq`X7NRv`!aP?qF#CO5 zvM7iR9lkRcVZQug(uNyVS+=d%A&1eiSauJOHepK{xu8#$RyKZl8Jz3LZ(8a@O=+HO zjiYx|b=2=!hD|wLKw@XxSub~DLxM}&$PCU!IbTHCZ74aSkj4`puD>+>dX{#Tc!gU$ z=q}HL*RB6&n7Q5ydmuyd3K8hUa6T+V_b+v$rZB?56T~t2RYya>q5%amnX5o-`j01} zTwBj6#ZdV>!n&$WTmV0qr~`o$!??xqSw6S~Mx1!aM`x()a}97~S-o|#1Eb~W^@YR! zNamK*fEqZ}dTP9(chJ{z&UfJ>XWpXQ)=t|KI!#-%d)+{h6lTczcR{9^=UvR*ZnYsV z7ET5snVWXo*|f!(J%PnPfT{ASguhe;PRG6HK#FjcB=+eXE-n@(AqPXpj6` zLC#r)LM6C4;#5xJWEuIYwmbLM8r4xDai9>MIMTzv#BY|yrL1~lKRQ# zr^P@?*v4g~pHd310IAg5hVgv)n|yd`6S&F7Frs^T8N9*_eDNtCZhVY3f_fWhLeyL( zxCu!7vK%wYAv|J0BRzC*Z6}0Q0dmtcab*-jTP%Zi+Y@TfogR0F40fv`w*qbR4vdh~ zF@AOb{mMgZOu{E-xFFgj`)Nle+P07;LI?gas1g*YI3DBWC}pjNAmM+Gssu$UqqSbp zNCEQFhF-XD!q4n$Ti&|g&gQM?Ago{E<0^ItlKHRHb4YNhI~&pjQEE{4e_uc)4~fiY zprV<^HwRZ^lDV1Jz1u3_5mP{|?q?X>URglQ_%kK>@-hF z@K``{|Np*`N}Eu`4zygI?Y#I);<1Wjt=Bu-+8Sy*|Ghx%Ac+2U-VC(02CnRV`7{;j z1|=D0MW+P|jv=jH&{l!kht~aJY>Xo!4vaAbAm*JA?ZJ$m*6BOxu6(<7^4hbCr=nfC zR;Kl@kGr+*2%(pS$Un5bSl?FHDG6KuIS6P@#>f94mh%9^^hAPp0!knQTH!3{n98U@ z>1*k%?*iT1_+wB}?baIjJ8&+lcm4}JXeHB63-(Z4(s1op;28P*!lVP2dAaDHf;Nd8 z=e9514!F*}>tZ@6n16o=f2Rw=7H%Jh9)N>5fqS5Yg7Se{b}Z^YFO0R-^o$5&-c=Q0GR}I?EnA( literal 0 HcmV?d00001 diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt index 1591cbf6cc..e9a6ce5549 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineEvent.kt @@ -57,4 +57,6 @@ sealed interface TimelineEvent { data class EditPoll( val pollStartId: EventId, ) : TimelineItemPollEvent + + data object StopLiveLocationShare : TimelineItemEvent } 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 12e4e0b1d1..b83adca5ec 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 @@ -197,6 +197,7 @@ class TimelinePresenter( is TimelineEvent.EditPoll -> { navigator.navigateToEditPoll(event.pollStartId) } + is TimelineEvent.StopLiveLocationShare -> Unit 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/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index b253f45937..421c52c9ef 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 @@ -269,7 +269,9 @@ fun TimelineItemEventRow( if (displayThreadSummaries && timelineMode !is Timeline.Mode.Thread && event.threadInfo is TimelineItemThreadInfo.ThreadRoot) { ThreadSummaryView( modifier = if (event.isMine) { - Modifier.align(Alignment.End).padding(end = 16.dp) + Modifier + .align(Alignment.End) + .padding(end = 16.dp) } else { if (timelineRoomInfo.isDm) Modifier else Modifier.padding(start = 16.dp) }.padding(top = 2.dp), @@ -674,6 +676,7 @@ private fun MessageEventBubbleContent( .padding(horizontal = 8.dp, vertical = 4.dp) ) } + TimestampPosition.Hidden -> Box(modifier) { content {} } } } @@ -763,11 +766,11 @@ private fun MessageEventBubbleContent( } } - val timestampPosition = when (event.content) { - is TimelineItemImageContent -> if (event.content.showCaption) TimestampPosition.Aligned else TimestampPosition.Overlay - is TimelineItemVideoContent -> if (event.content.showCaption) TimestampPosition.Aligned else TimestampPosition.Overlay - is TimelineItemStickerContent, - is TimelineItemLocationContent -> TimestampPosition.Overlay + val timestampPosition = when (val content = event.content) { + is TimelineItemImageContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Overlay + is TimelineItemVideoContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Overlay + is TimelineItemStickerContent -> TimestampPosition.Overlay + is TimelineItemLocationContent -> if (content.hideTimestamp) TimestampPosition.Hidden else TimestampPosition.Overlay is TimelineItemPollContent -> TimestampPosition.Below else -> TimestampPosition.Default } @@ -833,25 +836,27 @@ internal fun TimelineItemEventRowWithThreadSummaryPreview() = ElementPreview { groupPosition = TimelineItemGroupPosition.First, threadInfo = TimelineItemThreadInfo.ThreadRoot( latestEventText = "This is the latest message in the thread", - summary = ThreadSummary(AsyncData.Success( - EmbeddedEventInfo( - eventOrTransactionId = EventOrTransactionId.Event(EventId("\$event-id")), - content = MessageContent( - body = "This is the latest message in the thread", - inReplyTo = null, - isEdited = false, - threadInfo = null, - type = TextMessageType("This is the latest message in the thread", null) - ), - senderId = UserId("@user:id"), - senderProfile = ProfileDetails.Ready( - displayName = "Alice", - avatarUrl = null, - displayNameAmbiguous = false, - ), - timestamp = 0L, - ) - ), numberOfReplies = 20L) + summary = ThreadSummary( + AsyncData.Success( + EmbeddedEventInfo( + eventOrTransactionId = EventOrTransactionId.Event(EventId("\$event-id")), + content = MessageContent( + body = "This is the latest message in the thread", + inReplyTo = null, + isEdited = false, + threadInfo = null, + type = TextMessageType("This is the latest message in the thread", null) + ), + senderId = UserId("@user:id"), + senderProfile = ProfileDetails.Ready( + displayName = "Alice", + avatarUrl = null, + displayNameAmbiguous = false, + ), + timestamp = 0L, + ) + ), numberOfReplies = 20L + ) ) ), displayThreadSummaries = true, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimestampPosition.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimestampPosition.kt index 605db65da3..505edeef15 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimestampPosition.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimestampPosition.kt @@ -22,7 +22,12 @@ enum class TimestampPosition { /** * Timestamp should always be rendered below the timeline event content (eg. poll). */ - Below; + Below, + + /** + * Timestamp should be hidden. + */ + Hidden; companion object { /** diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt index 4fc243864c..1de73f3658 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt @@ -73,6 +73,7 @@ fun TimelineItemEventContentView( ) is TimelineItemLocationContent -> TimelineItemLocationView( content = content, + onStopLiveLocationClick = { eventSink(TimelineEvent.StopLiveLocationShare) }, modifier = modifier ) is TimelineItemImageContent -> TimelineItemImageView( 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 576f7bd2d5..c9e3152afb 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 @@ -8,33 +8,147 @@ package io.element.android.features.messages.impl.timeline.components.event +import androidx.compose.foundation.background +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.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color 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.StaticMapView import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.IconButton +import io.element.android.libraries.designsystem.theme.components.Text @Composable fun TimelineItemLocationView( content: TimelineItemLocationContent, + onStopLiveLocationClick: () -> Unit, modifier: Modifier = Modifier, ) { - StaticMapView( + Box(modifier = modifier.fillMaxWidth()) { + StaticMapView( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 188.dp), + pinVariant = content.pinVariant, + location = content.location, + zoom = 15.0, + contentDescription = content.description + ) + + if (content.mode is TimelineItemLocationContent.Mode.Live) { + LiveLocationOverlay( + mode = content.mode, + onStopClick = onStopLiveLocationClick, + modifier = Modifier.align(Alignment.BottomStart) + ) + } + } +} + +@Composable +private fun LiveLocationOverlay( + mode: TimelineItemLocationContent.Mode.Live, + onStopClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( modifier = modifier .fillMaxWidth() - .heightIn(max = 188.dp), - pinVariant = content.pinVariant, - lat = content.location.lat, - lon = content.location.lon, - zoom = 15.0, - contentDescription = content.description - ) + .background(ElementTheme.colors.bgCanvasDefault.copy(alpha = 0.9f)) + .padding(horizontal = 8.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val iconShape = RoundedCornerShape(8.dp) + Box( + modifier = Modifier + .size(32.dp) + .border( + width = 1.dp, + color = if (mode.isActive) ElementTheme.colors.iconQuaternaryAlpha else Color.Transparent, + shape = iconShape, + ) + .background( + color = if (mode.isActive) { + ElementTheme.colors.bgCanvasDefault + } else { + ElementTheme.colors.bgSubtleSecondary + }, + shape = iconShape + ) + ) { + if (mode.isLoading) { + CircularProgressIndicator( + strokeWidth = 2.dp, + color = ElementTheme.colors.iconSecondary, + modifier = Modifier + .align(Alignment.Center) + .size(20.dp) + ) + } else { + Icon( + imageVector = CompoundIcons.LocationPinSolid(), + contentDescription = null, + tint = if (mode.isActive) { + ElementTheme.colors.iconAccentPrimary + } else { + ElementTheme.colors.iconDisabled + }, + modifier = Modifier.align(Alignment.Center) + ) + } + } + Spacer(Modifier.width(8.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = if (mode.isActive) "Live location" else "Live location ended", + style = ElementTheme.typography.fontBodySmMedium, + color = ElementTheme.colors.textPrimary, + ) + if (mode.isActive) { + Text( + text = mode.endsAt, + style = ElementTheme.typography.fontBodySmRegular, + color = ElementTheme.colors.textPrimary, + ) + } + } + + if (mode.isActive && mode.canStop) { + IconButton( + onClick = onStopClick, + colors = IconButtonDefaults.iconButtonColors( + containerColor = ElementTheme.colors.bgCriticalPrimary, + contentColor = ElementTheme.colors.iconOnSolidPrimary, + ) + ) { + Icon( + imageVector = CompoundIcons.Stop(), + contentDescription = null, + ) + } + } + } } @PreviewsDayNight @@ -43,5 +157,6 @@ internal fun TimelineItemLocationViewPreview(@PreviewParameter(TimelineItemLocat ElementPreview { TimelineItemLocationView( content = content, + onStopLiveLocationClick = {}, ) } 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 85fa8a0dc1..a9457edfa4 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 @@ -15,6 +15,8 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent +import io.element.android.libraries.dateformatter.api.DateFormatter +import io.element.android.libraries.dateformatter.api.DateFormatterMode import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.UserId @@ -103,18 +105,18 @@ class TimelineItemContentFactory( val lastKnownLocation = itemContent.locations.mapNotNull { beacon -> Location.fromGeoUri(beacon.geoUri) }.lastOrNull() - if (lastKnownLocation != null) { - TimelineItemLocationContent( - description = itemContent.description?.trimEnd(), - assetType = itemContent.assetType, - senderId = sender, - senderProfile = senderProfile, - location = lastKnownLocation, - mode = TimelineItemLocationContent.Mode.Live(isActive = itemContent.isLive) - ) - } else { - TimelineItemUnknownContent - } + // Always create content - location can be null for "loading/waiting" state + TimelineItemLocationContent( + description = itemContent.description?.trimEnd(), + assetType = itemContent.assetType, + senderId = sender, + senderProfile = senderProfile, + mode = TimelineItemLocationContent.Mode.Live( + lastKnownLocation = lastKnownLocation, + isActive = itemContent.isLive, + endsAt = "", + ), + ) } } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt index a5e2f922ad..e2e5d0c03e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactory.kt @@ -150,12 +150,11 @@ class TimelineItemContentMessageFactory( ) } else { TimelineItemLocationContent( - location = location, description = messageType.description, senderId = senderId, senderProfile = senderProfile, assetType = messageType.assetType, - mode = TimelineItemLocationContent.Mode.Static + mode = TimelineItemLocationContent.Mode.Static(location = location) ) } } 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 f3d70f44e7..9683a2c149 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 @@ -35,7 +35,7 @@ class TimelineItemEventContentProvider : PreviewParameterProvider mode.lastKnownLocation + is Mode.Static -> mode.location + } + + /** + * The pin variant to display on the map. + * Returns a default variant when location is null (map will show loading placeholder anyway). + */ + val pinVariant: PinVariant = when (mode) { is Mode.Live -> { if (mode.isActive) { PinVariant.UserLocation(avatarData = senderAvatar(), isLive = true) @@ -34,7 +45,7 @@ data class TimelineItemLocationContent( PinVariant.StaleLocation } } - Mode.Static -> { + is Mode.Static -> { when (assetType) { AssetType.PIN -> PinVariant.PinnedLocation AssetType.SENDER, @@ -52,8 +63,18 @@ data class TimelineItemLocationContent( ) sealed interface Mode { - data object Static : Mode - data class Live(val isActive: Boolean) : Mode + data class Static( + val location: Location, + ) : Mode + + data class Live( + val lastKnownLocation: Location?, + val isActive: Boolean, + val endsAt: String, + val canStop: Boolean = false + ) : Mode { + val isLoading = lastKnownLocation == null && isActive + } } override val type: String = "TimelineItemLocationContent" diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt index 5c87c5c538..e2309c2210 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt @@ -18,8 +18,35 @@ open class TimelineItemLocationContentProvider : PreviewParameterProvider get() = sequenceOf( aTimelineItemLocationContent(), - aTimelineItemLocationContent(mode = TimelineItemLocationContent.Mode.Live(isActive = true)), - aTimelineItemLocationContent(mode = TimelineItemLocationContent.Mode.Live(isActive = false)), + aTimelineItemLocationContent( + mode = TimelineItemLocationContent.Mode.Live( + isActive = true, + endsAt = "Ends at 12:34", + canStop = true, + lastKnownLocation = aLocation() + ), + ), + aTimelineItemLocationContent( + mode = TimelineItemLocationContent.Mode.Live( + isActive = true, + endsAt = "Ends at 12:34", + lastKnownLocation = aLocation() + ), + ), + aTimelineItemLocationContent( + mode = TimelineItemLocationContent.Mode.Live( + isActive = true, + endsAt = "Ends at 12:34", + lastKnownLocation = null + ), + ), + aTimelineItemLocationContent( + mode = TimelineItemLocationContent.Mode.Live( + isActive = false, + endsAt = "", + lastKnownLocation = aLocation() + ), + ), ) } @@ -27,15 +54,16 @@ fun aTimelineItemLocationContent( senderId: UserId = UserId("@sender:matrix.org"), senderProfile: ProfileDetails = aProfileDetailsReady(), description: String? = null, - mode: TimelineItemLocationContent.Mode = TimelineItemLocationContent.Mode.Static, + mode: TimelineItemLocationContent.Mode = TimelineItemLocationContent.Mode.Static(aLocation()), ) = TimelineItemLocationContent( - location = Location( - lat = 52.2445, - lon = 0.7186, - accuracy = 5000f, - ), senderId = senderId, senderProfile = senderProfile, description = description, - mode = mode + mode = mode, +) + +fun aLocation() = Location( + lat = 52.2445, + lon = 0.7186, + accuracy = 5000f, ) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index 957b01d1ed..969e27e8a4 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -110,7 +110,6 @@ class TimelineItemContentMessageFactoryTest { eventId = AN_EVENT_ID, ) val expected = TimelineItemLocationContent( - body = "body", location = Location(lat = 1.0, lon = 2.0, accuracy = null), description = "description", assetType = assetType, From bf7ab3151703581e90d56295bfc7807ce97fa3bc Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Wed, 25 Mar 2026 00:53:57 +0100 Subject: [PATCH 05/44] feat: support sending voice messages as replies --- .../DefaultVoiceMessageComposerPresenter.kt | 33 ++++++++++------- ...efaultVoiceMessageComposerPresenterTest.kt | 36 +++++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt index 6fdd2f1752..a14a471571 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt @@ -34,10 +34,12 @@ import io.element.android.libraries.audio.api.AudioFocus import io.element.android.libraries.audio.api.AudioFocusRequester import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.annotations.SessionCoroutineScope +import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.timeline.Timeline import io.element.android.libraries.mediaupload.api.MediaSenderFactory import io.element.android.libraries.permissions.api.PermissionsEvent import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.libraries.textcomposer.model.MessageComposerMode import io.element.android.libraries.textcomposer.model.VoiceMessagePlayerEvent import io.element.android.libraries.textcomposer.model.VoiceMessageRecorderEvent import io.element.android.libraries.textcomposer.model.VoiceMessageState @@ -151,7 +153,7 @@ class DefaultVoiceMessageComposerPresenter( } } - fun sendVoiceMessage() { + fun sendVoiceMessage(inReplyToEventId: EventId?, composerEvent: Composer) { val finishedState = recorderState as? VoiceRecorderState.Finished if (finishedState == null) { val exception = VoiceMessageException.FileException("No file to send") @@ -164,12 +166,13 @@ class DefaultVoiceMessageComposerPresenter( } isSending = true player.pause() - analyticsService.captureComposerEvent() + analyticsService.capture(composerEvent) sessionCoroutineScope.launch { val result = sendMessage( file = finishedState.file, mimeType = finishedState.mimeType, waveform = finishedState.waveform, + inReplyToEventId = inReplyToEventId, ) if (result.isFailure) { showSendFailureDialog = true @@ -183,8 +186,14 @@ class DefaultVoiceMessageComposerPresenter( when (event) { is VoiceMessageComposerEvent.RecorderEvent -> handleVoiceMessageRecorderEvent(event.recorderEvent) is VoiceMessageComposerEvent.PlayerEvent -> handleVoiceMessagePlayerEvent(event.playerEvent) - is VoiceMessageComposerEvent.SendVoiceMessage -> localCoroutineScope.launch { - sendVoiceMessage() + is VoiceMessageComposerEvent.SendVoiceMessage -> { + // Capture mode eagerly before any coroutine dispatch, since CloseSpecialMode + // may reset it before the coroutine runs. + val inReplyToEventId = (messageComposerContext.composerMode as? MessageComposerMode.Reply)?.eventId + val composerEvent = buildComposerEvent() + localCoroutineScope.launch { + sendVoiceMessage(inReplyToEventId, composerEvent) + } } VoiceMessageComposerEvent.DeleteVoiceMessage -> { player.pause() @@ -280,11 +289,13 @@ class DefaultVoiceMessageComposerPresenter( file: File, mimeType: String, waveform: List, + inReplyToEventId: EventId? = null, ): Result { val result = mediaSender.sendVoiceMessage( uri = file.toUri(), mimeType = mimeType, waveForm = waveform, + inReplyToEventId = inReplyToEventId, ) if (result.isFailure) { @@ -297,14 +308,12 @@ class DefaultVoiceMessageComposerPresenter( return result } - private fun AnalyticsService.captureComposerEvent() = - capture( - Composer( - inThread = messageComposerContext.composerMode.inThread, - isEditing = messageComposerContext.composerMode.isEditing, - isReply = messageComposerContext.composerMode.isReply, - messageType = Composer.MessageType.VoiceMessage, - ) + private fun buildComposerEvent() = + Composer( + inThread = messageComposerContext.composerMode.inThread, + isEditing = messageComposerContext.composerMode.isEditing, + isReply = messageComposerContext.composerMode.isReply, + messageType = Composer.MessageType.VoiceMessage, ) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt index 9c55bf3a85..5323ccd6f0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.audio.api.AudioFocusRequester import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.media.AudioInfo import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.timeline.FakeTimeline @@ -46,7 +47,9 @@ import io.element.android.libraries.voicerecorder.api.VoiceRecorder import io.element.android.libraries.voicerecorder.test.FakeVoiceRecorder import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.lambda.any 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.collections.immutable.toImmutableList import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -59,6 +62,7 @@ import java.io.File import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds +@Suppress("LargeClass") class DefaultVoiceMessageComposerPresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -406,6 +410,38 @@ class DefaultVoiceMessageComposerPresenterTest { } } + @Test + fun `present - send voice message passes reply event ID only when in reply mode`() = runTest { + val presenter = createDefaultVoiceMessageComposerPresenter() + presenter.test { + // Send without reply - should pass null + messageComposerContext.composerMode = MessageComposerMode.Normal + awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Start)) + awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Stop)) + awaitItem().eventSink(VoiceMessageComposerEvent.SendVoiceMessage) + skipItems(1) // Sending state + advanceUntilIdle() + + sendVoiceMessageResult.assertions().isCalledOnce() + .with(any(), any(), any(), value(null)) + + // Send as reply - should pass event ID + messageComposerContext.composerMode = aReplyMode() + awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Start)) + awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Stop)) + awaitItem().eventSink(VoiceMessageComposerEvent.SendVoiceMessage) + val finalState = awaitItem() // Sending state + + sendVoiceMessageResult.assertions().isCalledExactly(2) + .withSequence( + listOf(any(), any(), any(), value(null)), + listOf(any(), any(), any(), value(AN_EVENT_ID)), + ) + + testPauseAndDestroy(finalState) + } + } + @Test fun `present - send while playing`() = runTest { val presenter = createDefaultVoiceMessageComposerPresenter() From 4a5662a5e25547f21b588a7aeeca99a6af9b48f8 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Wed, 25 Mar 2026 00:55:57 +0100 Subject: [PATCH 06/44] fix: reset composer mode after sending voice message reply --- .../messages/impl/messagecomposer/MessageComposerView.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt index 4b346e0c15..48baf245fa 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerView.kt @@ -83,6 +83,7 @@ internal fun MessageComposerView( val onSendVoiceMessage = { voiceMessageState.eventSink(VoiceMessageComposerEvent.SendVoiceMessage) + state.eventSink(MessageComposerEvent.CloseSpecialMode) } val onDeleteVoiceMessage = { From d9a54fb716b6edd73e8d03e2130838e1f3570f33 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Wed, 25 Mar 2026 00:58:57 +0100 Subject: [PATCH 07/44] fix: persist reply banner during voice recording and dismiss keyboard --- .../libraries/textcomposer/TextComposer.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index bdaed4e402..360e81e426 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -41,6 +41,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback +import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.clearAndSetSemantics @@ -400,6 +401,7 @@ fun TextComposer( onAddAttachment = onAddAttachment, onDeleteVoiceMessage = onDeleteVoiceMessage, onVoiceRecorderEvent = onVoiceRecorderEvent, + onResetComposerMode = onResetComposerMode, ) } @@ -409,6 +411,14 @@ fun TextComposer( SoftKeyboardEffect(showTextFormatting, onRequestFocus) { it } + // Dismiss keyboard when voice recording starts + val keyboardController = LocalSoftwareKeyboardController.current + LaunchedEffect(voiceMessageState) { + if (voiceMessageState !is VoiceMessageState.Idle) { + keyboardController?.hide() + } + } + val latestOnReceiveSuggestion by rememberUpdatedState(onReceiveSuggestion) if (state is TextEditorState.Rich) { val menuAction = state.richTextEditorState.menuAction @@ -440,6 +450,7 @@ private fun StandardLayout( onAddAttachment: () -> Unit, onDeleteVoiceMessage: () -> Unit, onVoiceRecorderEvent: (VoiceMessageRecorderEvent) -> Unit, + onResetComposerMode: () -> Unit, modifier: Modifier = Modifier, ) { Column(modifier = modifier) { @@ -506,6 +517,14 @@ private fun StandardLayout( ) { if (voiceMessageState is VoiceMessageState.Idle) { textInput() + } else if (composerMode is MessageComposerMode.Special) { + TextInputBox( + composerMode = composerMode, + onResetComposerMode = onResetComposerMode, + isTextEmpty = true, + ) { + voiceRecording() + } } else { voiceRecording() } From a7e254cc8414c43920c178f9ee57d29b9ca71798 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 25 Mar 2026 19:57:34 +0100 Subject: [PATCH 08/44] Live location : format the endsAt timeline item content --- .../factories/event/TimelineItemContentFactory.kt | 13 +++++++++++-- .../matrix/api/timeline/item/event/EventContent.kt | 5 ++++- .../item/event/TimelineEventContentMapper.kt | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) 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 a9457edfa4..8b81ae0906 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 @@ -38,6 +38,8 @@ import io.element.android.libraries.matrix.api.timeline.item.event.StickerConten import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.services.toolbox.api.strings.StringProvider @Inject class TimelineItemContentFactory( @@ -52,6 +54,8 @@ class TimelineItemContentFactory( private val failedToParseMessageFactory: TimelineItemContentFailedToParseMessageFactory, private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory, private val sessionId: SessionId, + private val dateFormatter: DateFormatter, + private val stringProvider: StringProvider, ) { suspend fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { return create( @@ -105,7 +109,12 @@ class TimelineItemContentFactory( val lastKnownLocation = itemContent.locations.mapNotNull { beacon -> Location.fromGeoUri(beacon.geoUri) }.lastOrNull() - // Always create content - location can be null for "loading/waiting" state + + val endsAt = dateFormatter.format( + timestamp = itemContent.endsAt, + mode = DateFormatterMode.TimeOnly + ) + // Always create content, location can be null for "loading/waiting" state TimelineItemLocationContent( description = itemContent.description?.trimEnd(), assetType = itemContent.assetType, @@ -114,7 +123,7 @@ class TimelineItemContentFactory( mode = TimelineItemLocationContent.Mode.Live( lastKnownLocation = lastKnownLocation, isActive = itemContent.isLive, - endsAt = "", + endsAt = stringProvider.getString(CommonStrings.common_ends_at, endsAt), ), ) } 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 35c37fc4a9..931287cfe7 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 @@ -107,10 +107,13 @@ data class FailedToParseStateContent( data class LiveLocationContent( val isLive: Boolean, val description: String?, + val timestamp: Long, val timeout: Long, val assetType: AssetType?, val locations: List, -) : EventContent +) : EventContent { + val endsAt = timestamp + timeout +} data object LegacyCallInviteContent : EventContent 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 24a4c97fbf..11d107cd8b 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 @@ -114,6 +114,7 @@ class TimelineEventContentMapper( is MsgLikeKind.LiveLocation -> { LiveLocationContent( isLive = kind.content.isLive, + timestamp = kind.content.ts.toLong(), description = kind.content.description, timeout = kind.content.timeoutMs.toLong(), assetType = kind.content.assetType.into(), From 55d043788b0ae15e8fad84094d7e9f10c6b1e9c1 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Thu, 26 Mar 2026 09:08:45 +0400 Subject: [PATCH 09/44] Reorder theme options in AdvancedSettingsState --- .../impl/advanced/AdvancedSettingsState.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 be443e905b..7cb9e9ce86 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 @@ -43,6 +43,13 @@ enum class ThemeOption : DropdownOption { @ReadOnlyComposable override fun getText(): String = stringResource(CommonStrings.common_system) }, + + Light { + @Composable + @ReadOnlyComposable + override fun getText(): String = stringResource(CommonStrings.common_light) + }, + Dark { @Composable @ReadOnlyComposable @@ -53,11 +60,5 @@ enum class ThemeOption : DropdownOption { @Composable @ReadOnlyComposable override fun getText(): String = stringResource(CommonStrings.common_black) - }, - - Light { - @Composable - @ReadOnlyComposable - override fun getText(): String = stringResource(CommonStrings.common_light) } } From 37da07a7208b9a9235638f27fc733fe5a2d15949 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Fri, 27 Mar 2026 21:18:55 +0100 Subject: [PATCH 10/44] Revert unnecessary analytics refactor in voice message presenter --- .../DefaultVoiceMessageComposerPresenter.kt | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt index a14a471571..96d1787085 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenter.kt @@ -153,7 +153,7 @@ class DefaultVoiceMessageComposerPresenter( } } - fun sendVoiceMessage(inReplyToEventId: EventId?, composerEvent: Composer) { + fun sendVoiceMessage(inReplyToEventId: EventId?) { val finishedState = recorderState as? VoiceRecorderState.Finished if (finishedState == null) { val exception = VoiceMessageException.FileException("No file to send") @@ -166,7 +166,7 @@ class DefaultVoiceMessageComposerPresenter( } isSending = true player.pause() - analyticsService.capture(composerEvent) + analyticsService.captureComposerEvent() sessionCoroutineScope.launch { val result = sendMessage( file = finishedState.file, @@ -187,12 +187,11 @@ class DefaultVoiceMessageComposerPresenter( is VoiceMessageComposerEvent.RecorderEvent -> handleVoiceMessageRecorderEvent(event.recorderEvent) is VoiceMessageComposerEvent.PlayerEvent -> handleVoiceMessagePlayerEvent(event.playerEvent) is VoiceMessageComposerEvent.SendVoiceMessage -> { - // Capture mode eagerly before any coroutine dispatch, since CloseSpecialMode - // may reset it before the coroutine runs. + // Capture reply info eagerly before any coroutine dispatch, since CloseSpecialMode + // may reset composerMode before the coroutine runs. val inReplyToEventId = (messageComposerContext.composerMode as? MessageComposerMode.Reply)?.eventId - val composerEvent = buildComposerEvent() localCoroutineScope.launch { - sendVoiceMessage(inReplyToEventId, composerEvent) + sendVoiceMessage(inReplyToEventId) } } VoiceMessageComposerEvent.DeleteVoiceMessage -> { @@ -308,12 +307,14 @@ class DefaultVoiceMessageComposerPresenter( return result } - private fun buildComposerEvent() = - Composer( - inThread = messageComposerContext.composerMode.inThread, - isEditing = messageComposerContext.composerMode.isEditing, - isReply = messageComposerContext.composerMode.isReply, - messageType = Composer.MessageType.VoiceMessage, + private fun AnalyticsService.captureComposerEvent() = + capture( + Composer( + inThread = messageComposerContext.composerMode.inThread, + isEditing = messageComposerContext.composerMode.isEditing, + isReply = messageComposerContext.composerMode.isReply, + messageType = Composer.MessageType.VoiceMessage, + ) ) } From 104ae4752a831ac4be23ff8d767d4087e32857c3 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Thu, 2 Apr 2026 17:28:55 +0400 Subject: [PATCH 11/44] Reorder imports to align with static analysis --- .../features/preferences/impl/advanced/AdvancedSettingsView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f8f1faebbd..2e4d6f9ce5 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 @@ -28,8 +28,8 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewBlack +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 From 9a81ec5569bb624e2fa6a85e8f146e023d9c0400 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Thu, 2 Apr 2026 22:14:04 +0200 Subject: [PATCH 12/44] refactor: remove keyboard dismissal logic during voice recording --- .../android/libraries/textcomposer/TextComposer.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 360e81e426..4f61b13fb5 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -41,7 +41,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.clearAndSetSemantics @@ -411,13 +410,6 @@ fun TextComposer( SoftKeyboardEffect(showTextFormatting, onRequestFocus) { it } - // Dismiss keyboard when voice recording starts - val keyboardController = LocalSoftwareKeyboardController.current - LaunchedEffect(voiceMessageState) { - if (voiceMessageState !is VoiceMessageState.Idle) { - keyboardController?.hide() - } - } val latestOnReceiveSuggestion by rememberUpdatedState(onReceiveSuggestion) if (state is TextEditorState.Rich) { From 4586ee31ea0afc75b5ca080abae59b628e5f99c2 Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Thu, 2 Apr 2026 22:20:13 +0200 Subject: [PATCH 13/44] fix: re-focus text input after voice recording ends --- .../android/libraries/textcomposer/TextComposer.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 4f61b13fb5..5a3ee1c8a0 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -410,6 +410,14 @@ fun TextComposer( SoftKeyboardEffect(showTextFormatting, onRequestFocus) { it } + // Re-focus the text input when voice recording ends so the user can continue typing + var previousVoiceMessageState by remember { mutableStateOf(voiceMessageState) } + LaunchedEffect(voiceMessageState) { + if (voiceMessageState is VoiceMessageState.Idle && previousVoiceMessageState !is VoiceMessageState.Idle) { + onRequestFocus() + } + previousVoiceMessageState = voiceMessageState + } val latestOnReceiveSuggestion by rememberUpdatedState(onReceiveSuggestion) if (state is TextEditorState.Rich) { From 4e0165458a3c15b90ddc45786c5337490f08b1f9 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 3 Apr 2026 18:21:37 +0200 Subject: [PATCH 14/44] Live location : start collecting live location --- .../impl/show/ShowLocationPresenter.kt | 46 ++++- .../show/DefaultShowLocationEntryPointTest.kt | 4 +- .../impl/show/ShowLocationPresenterTest.kt | 177 +++++++++++++++++- .../messages/impl/MessagesFlowNode.kt | 23 +-- .../api/room/location/LiveLocationShare.kt | 2 - .../matrix/impl/room/JoinedRustRoom.kt | 11 +- .../room/location/LiveLocationShareMapper.kt | 21 --- .../room/location/LiveLocationSharesFlow.kt | 60 ++++++ 8 files changed, 295 insertions(+), 49 deletions(-) delete mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationShareMapper.kt create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt 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 a2c9a3702d..b72c01e697 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 @@ -13,11 +13,13 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.produceState import androidx.compose.runtime.remember 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.impl.common.LocationConstraintsCheck import io.element.android.features.location.impl.common.MapDefaults @@ -29,14 +31,21 @@ import io.element.android.features.location.impl.common.permissions.PermissionsS import io.element.android.features.location.impl.common.toDialogState import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.core.coroutine.mapState import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.dateformatter.api.DateFormatter import io.element.android.libraries.dateformatter.api.DateFormatterMode import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.matrix.api.room.JoinedRoom +import io.element.android.libraries.matrix.api.room.getBestName +import io.element.android.libraries.matrix.api.room.joinedRoomMembers +import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.flow.combine @AssistedInject class ShowLocationPresenter( @@ -46,6 +55,7 @@ class ShowLocationPresenter( private val buildMeta: BuildMeta, private val dateFormatter: DateFormatter, private val stringProvider: StringProvider, + private val joinedRoom: JoinedRoom, ) : Presenter { @AssistedFactory fun interface Factory { @@ -96,9 +106,9 @@ class ShowLocationPresenter( } } - val locationShares = remember { - when (mode) { - is ShowLocationMode.Static -> { + val locationShares = when (mode) { + is ShowLocationMode.Static -> { + remember { val relativeTime = dateFormatter.format(timestamp = mode.timestamp, mode = DateFormatterMode.Full, useRelative = true) val formattedTimestamp = stringProvider.getString( CommonStrings.screen_static_location_sheet_timestamp_description, @@ -121,7 +131,35 @@ class ShowLocationPresenter( ) ) } - ShowLocationMode.Live -> persistentListOf() + } + ShowLocationMode.Live -> { + val liveShares by produceState(persistentListOf()) { + val liveLocationSharesFlow = joinedRoom.subscribeToLiveLocationShares() + val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() } + combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members -> + liveShares.mapNotNull { share -> + val location = Location.fromGeoUri(share.lastGeoUri) ?: return@mapNotNull null + val member = members.find { it.userId == share.userId } + val displayName = member?.getBestName() ?: share.userId.value + val avatarUrl = member?.avatarUrl + LocationShareItem( + userId = share.userId, + displayName = displayName, + avatarData = AvatarData( + id = share.userId.value, + name = displayName, + url = avatarUrl, + size = AvatarSize.UserListItem, + ), + formattedTimestamp = "Sharing live location", + location = location, + isLive = true, + assetType = AssetType.SENDER, + ) + }.toPersistentList() + }.collect { value = it } + } + liveShares } } 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 451531fc7e..91df447e2a 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 @@ -19,6 +19,7 @@ import io.element.android.features.location.impl.common.permissions.FakePermissi 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 +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.node.TestParentNode @@ -43,7 +44,8 @@ class DefaultShowLocationEntryPointTest { locationActions = FakeLocationActions(), buildMeta = aBuildMeta(), dateFormatter = FakeDateFormatter(), - stringProvider = FakeStringProvider() + stringProvider = FakeStringProvider(), + joinedRoom = FakeJoinedRoom(), ) }, analyticsService = FakeAnalyticsService(), 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 931dd55cea..81ec465686 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 @@ -22,11 +22,17 @@ import io.element.android.features.location.impl.common.permissions.PermissionsS import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState 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.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.FakeLiveLocationShareService import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -51,13 +57,15 @@ class ShowLocationPresenterTest { assetType = null, ), locationActions: FakeLocationActions = fakeLocationActions, + joinedRoom: JoinedRoom = FakeJoinedRoom(), ) = ShowLocationPresenter( mode = mode, permissionsPresenterFactory = { fakePermissionsPresenter }, locationActions = locationActions, buildMeta = fakeBuildMeta, dateFormatter = fakeDateFormatter, - stringProvider = FakeStringProvider() + stringProvider = FakeStringProvider(), + joinedRoom = joinedRoom, ) @Test @@ -318,4 +326,171 @@ class ShowLocationPresenterTest { assertThat(fakeLocationActions.openLocationSettingsInvocationsCount).isEqualTo(1) } } + + @Test + fun `live mode emits empty location shares initially`() = runTest { + val presenter = createShowLocationPresenter( + mode = ShowLocationMode.Live, + joinedRoom = FakeJoinedRoom(), + ) + presenter.test { + val initialState = awaitItem() + assertThat(initialState.locationShares).isEmpty() + assertThat(initialState.isSheetDraggable).isFalse() + } + } + + @Test + fun `live mode collects live shares from room`() = runTest { + val userId = UserId("@bob:matrix.org") + val liveSharesFlow = MutableStateFlow( + listOf( + LiveLocationShare( + userId = userId, + lastGeoUri = "geo:48.8584,2.2945", + lastTimestamp = 1234567890L, + isLive = true, + ) + ) + ) + val fakeRoom = FakeJoinedRoom( + liveLocationShareService = FakeLiveLocationShareService( + liveLocationSharesFlow = liveSharesFlow + ) + ) + + val presenter = createShowLocationPresenter( + mode = ShowLocationMode.Live, + joinedRoom = fakeRoom, + ) + presenter.test { + // Skip initial empty state from collectAsState(initial = emptyList()) + skipItems(1) + val state = awaitItem() + + assertThat(state.locationShares).hasSize(1) + val item = state.locationShares.first() + assertThat(item.userId).isEqualTo(userId) + assertThat(item.location.lat).isEqualTo(48.8584) + assertThat(item.location.lon).isEqualTo(2.2945) + assertThat(item.isLive).isTrue() + assertThat(state.isSheetDraggable).isTrue() + } + } + + @Test + fun `live mode handles invalid geo uri gracefully`() = runTest { + val validUserId = UserId("@alice:matrix.org") + val invalidUserId = UserId("@bob:matrix.org") + val liveSharesFlow = MutableStateFlow( + listOf( + LiveLocationShare( + userId = validUserId, + lastGeoUri = "geo:48.8584,2.2945", + lastTimestamp = 1234567890L, + isLive = true, + ), + LiveLocationShare( + userId = invalidUserId, + lastGeoUri = "invalid-geo-uri", + lastTimestamp = 1234567890L, + isLive = true, + ), + ) + ) + val fakeRoom = FakeJoinedRoom( + liveLocationShareService = FakeLiveLocationShareService( + liveLocationSharesFlow = liveSharesFlow + ) + ) + + val presenter = createShowLocationPresenter( + mode = ShowLocationMode.Live, + joinedRoom = fakeRoom, + ) + presenter.test { + // Skip initial empty state from collectAsState(initial = emptyList()) + skipItems(1) + val state = awaitItem() + + // Only the valid location share should be present + assertThat(state.locationShares).hasSize(1) + assertThat(state.locationShares.first().userId).isEqualTo(validUserId) + } + } + + @Test + fun `live mode updates when shares change`() = runTest { + val userId = UserId("@bob:matrix.org") + val liveSharesFlow = MutableStateFlow(emptyList()) + val fakeRoom = FakeJoinedRoom( + liveLocationShareService = FakeLiveLocationShareService( + liveLocationSharesFlow = liveSharesFlow + ) + ) + + val presenter = createShowLocationPresenter( + mode = ShowLocationMode.Live, + joinedRoom = fakeRoom, + ) + presenter.test { + // Initial state is empty + val initialState = awaitItem() + assertThat(initialState.locationShares).isEmpty() + + // Emit a new live share + liveSharesFlow.value = listOf( + LiveLocationShare( + userId = userId, + lastGeoUri = "geo:48.8584,2.2945", + lastTimestamp = 1234567890L, + isLive = true, + ) + ) + + val updatedState = awaitItem() + assertThat(updatedState.locationShares).hasSize(1) + assertThat(updatedState.locationShares.first().userId).isEqualTo(userId) + } + } + + @Test + fun `static mode emits location share with correct data`() = runTest { + val senderId = UserId("@alice:matrix.org") + val senderName = "Alice" + val avatarUrl = "https://example.com/avatar.png" + val mode = ShowLocationMode.Static( + location = location, + senderName = senderName, + senderId = senderId, + senderAvatarUrl = avatarUrl, + timestamp = 1234567890L, + assetType = AssetType.SENDER, + ) + + val presenter = createShowLocationPresenter(mode = mode) + presenter.test { + val state = awaitItem() + assertThat(state.locationShares).hasSize(1) + + val item = state.locationShares.first() + assertThat(item.userId).isEqualTo(senderId) + assertThat(item.displayName).isEqualTo(senderName) + assertThat(item.location).isEqualTo(location) + assertThat(item.isLive).isFalse() + assertThat(item.assetType).isEqualTo(AssetType.SENDER) + assertThat(item.avatarData.id).isEqualTo(senderId.value) + assertThat(item.avatarData.name).isEqualTo(senderName) + assertThat(item.avatarData.url).isEqualTo(avatarUrl) + } + } + + @Test + fun `static mode has non-draggable sheet`() = runTest { + val presenter = createShowLocationPresenter() + presenter.test { + val state = awaitItem() + assertThat(state.isSheetDraggable).isFalse() + } + } } 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 38d0504258..2d6a0f8c68 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 @@ -558,17 +558,18 @@ class MessagesFlowNode( ) } is TimelineItemLocationContent -> { - val mode = ShowLocationMode.Static( - location = event.content.location, - senderName = event.safeSenderName, - senderId = event.senderId, - senderAvatarUrl = event.senderAvatar.url, - timestamp = event.sentTimeMillis, - assetType = event.content.assetType, - ) - NavTarget.LocationViewer( - mode = mode - ).takeIf { locationService.isServiceAvailable() } + val mode = when(event.content.mode){ + is TimelineItemLocationContent.Mode.Live -> ShowLocationMode.Live + is TimelineItemLocationContent.Mode.Static -> ShowLocationMode.Static( + location = event.content.mode.location, + senderName = event.safeSenderName, + senderId = event.senderId, + senderAvatarUrl = event.senderAvatar.url, + timestamp = event.sentTimeMillis, + assetType = event.content.assetType, + ) + } + NavTarget.LocationViewer(mode = mode).takeIf { locationService.isServiceAvailable() } } else -> null } 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 7e841639bd..5f9cd41462 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 @@ -19,6 +19,4 @@ data class LiveLocationShare( val lastGeoUri: String, /** The timestamp of the last location update. */ val lastTimestamp: Long, - /** Whether the live location share is still active. */ - val isLive: Boolean, ) 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 644c5aefc2..0c41824dde 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 @@ -43,7 +43,7 @@ import io.element.android.libraries.matrix.impl.mapper.map 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.map +import io.element.android.libraries.matrix.impl.room.location.liveLocationSharesFlow import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.timeline.RustTimeline @@ -68,7 +68,6 @@ 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.LiveLocationShareListener import org.matrix.rustcomponents.sdk.RoomMessageEventMessageType import org.matrix.rustcomponents.sdk.RoomSendQueueUpdate import org.matrix.rustcomponents.sdk.SendQueueListener @@ -504,13 +503,7 @@ class JoinedRustRoom( } override fun subscribeToLiveLocationShares(): Flow> { - return mxCallbackFlow { - innerRoom.subscribeToLiveLocationShares(object : LiveLocationShareListener { - override fun call(liveLocationShares: List) { - trySend(liveLocationShares.map { it.map() }) - } - }) - } + return innerRoom.liveLocationSharesFlow() } override suspend fun startLiveLocationShare(durationMillis: Long): Result = withContext(roomDispatcher) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationShareMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationShareMapper.kt deleted file mode 100644 index 3b80c1c61f..0000000000 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationShareMapper.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2025 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.UserId -import io.element.android.libraries.matrix.api.room.location.LiveLocationShare -import org.matrix.rustcomponents.sdk.LiveLocationShare as RustLiveLocationShare - -fun RustLiveLocationShare.map(): LiveLocationShare { - return LiveLocationShare( - userId = UserId(userId), - lastGeoUri = lastLocation.location.geoUri, - lastTimestamp = lastLocation.ts.toLong(), - isLive = isLive, - ) -} 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 new file mode 100644 index 0000000000..7b3a29cf4a --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/LiveLocationSharesFlow.kt @@ -0,0 +1,60 @@ +/* + * 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.UserId +import io.element.android.libraries.matrix.api.room.location.LiveLocationShare +import io.element.android.libraries.matrix.impl.util.mxCallbackFlow +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.buffer +import org.matrix.rustcomponents.sdk.LiveLocationShare as RustLiveLocationShare +import org.matrix.rustcomponents.sdk.LiveLocationShareListener +import org.matrix.rustcomponents.sdk.LiveLocationShareUpdate +import org.matrix.rustcomponents.sdk.RoomInterface + +fun RoomInterface.liveLocationSharesFlow(): Flow> { + fun MutableList.applyUpdate(update: LiveLocationShareUpdate) { + when (update) { + is LiveLocationShareUpdate.Append -> addAll(update.values.map { it.into() }) + is LiveLocationShareUpdate.Clear -> clear() + is LiveLocationShareUpdate.Insert -> add(update.index.toInt(), update.value.into()) + is LiveLocationShareUpdate.PopBack -> if (isNotEmpty()) removeAt(lastIndex) + is LiveLocationShareUpdate.PopFront -> if (isNotEmpty()) removeAt(0) + is LiveLocationShareUpdate.PushBack -> add(update.value.into()) + is LiveLocationShareUpdate.PushFront -> add(0, update.value.into()) + is LiveLocationShareUpdate.Remove -> removeAt(update.index.toInt()) + is LiveLocationShareUpdate.Reset -> { + clear() + addAll(update.values.map { it.into() }) + } + is LiveLocationShareUpdate.Set -> set(update.index.toInt(), update.value.into()) + is LiveLocationShareUpdate.Truncate -> subList(update.length.toInt(), size).clear() + } + } + return mxCallbackFlow { + val shares: MutableList = ArrayList() + subscribeToLiveLocationShares(object : LiveLocationShareListener { + override fun onUpdate(updates: List) { + for (update in updates) { + shares.applyUpdate(update) + } + trySend(shares) + } + }) + }.buffer(Channel.UNLIMITED) +} + +private fun RustLiveLocationShare.into(): LiveLocationShare { + return LiveLocationShare( + userId = UserId(userId), + lastGeoUri = lastLocation?.location?.geoUri.orEmpty(), + lastTimestamp = lastLocation?.ts?.toLong() ?: 0, + ) +} + From 5e6a6af409f7108d7e847fcae409b3a98bf5b456 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Sun, 5 Apr 2026 12:03:50 +0400 Subject: [PATCH 15/44] Add "Allow black theme" feature flag --- .../io/element/android/x/MainActivity.kt | 1 + .../android/appnav/LoggedInFlowNode.kt | 3 ++ .../call/impl/ui/ElementCallActivity.kt | 3 ++ .../call/impl/ui/IncomingCallActivity.kt | 5 +++ .../impl/unlock/activity/PinUnlockActivity.kt | 3 ++ .../advanced/AdvancedSettingsPresenter.kt | 17 +++++++- .../impl/advanced/AdvancedSettingsState.kt | 2 + .../advanced/AdvancedSettingsStateProvider.kt | 4 ++ .../impl/advanced/AdvancedSettingsView.kt | 3 +- .../advanced/AdvancedSettingsPresenterTest.kt | 41 +++++++++++++++++++ .../impl/advanced/AdvancedSettingsViewTest.kt | 28 +++++++++++++ .../element/android/compound/theme/Theme.kt | 8 +++- .../android/compound/theme/ThemeTest.kt | 11 +++++ libraries/designsystem/build.gradle.kts | 1 + .../designsystem/theme/ElementThemeApp.kt | 11 +++-- .../libraries/featureflag/api/FeatureFlags.kt | 7 ++++ 16 files changed, 139 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/io/element/android/x/MainActivity.kt b/app/src/main/kotlin/io/element/android/x/MainActivity.kt index b522edd137..e97a040e91 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -71,6 +71,7 @@ class MainActivity : NodeActivity() { }.collectAsState(SemanticColorsLightDark.default) ElementThemeApp( appPreferencesStore = appBindings.preferencesStore(), + featureFlagService = appBindings.featureFlagService(), compoundLight = colors.light, compoundDark = colors.dark, buildMeta = appBindings.buildMeta() 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 a676df1d32..6c7e554c37 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -77,6 +77,7 @@ import io.element.android.libraries.designsystem.theme.ElementThemeApp import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.annotations.SessionCoroutineScope +import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId @@ -144,6 +145,7 @@ class LoggedInFlowNode( private val syncService: SyncService, private val enterpriseService: EnterpriseService, private val appPreferencesStore: AppPreferencesStore, + private val featureFlagService: FeatureFlagService, private val buildMeta: BuildMeta, snackbarDispatcher: SnackbarDispatcher, private val analyticsService: AnalyticsService, @@ -667,6 +669,7 @@ class LoggedInFlowNode( }.collectAsState(SemanticColorsLightDark.default) ElementThemeApp( appPreferencesStore = appPreferencesStore, + featureFlagService = featureFlagService, compoundLight = colors.light, compoundDark = colors.dark, buildMeta = buildMeta, 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 bf4f836294..5fa3beb36a 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 @@ -54,6 +54,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.featureflag.api.FeatureFlagService import io.element.android.libraries.preferences.api.store.AppPreferencesStore import timber.log.Timber @@ -66,6 +67,7 @@ class ElementCallActivity : @Inject lateinit var callIntentDataParser: CallIntentDataParser @Inject lateinit var presenterFactory: CallScreenPresenter.Factory @Inject lateinit var appPreferencesStore: AppPreferencesStore + @Inject lateinit var featureFlagService: FeatureFlagService @Inject lateinit var enterpriseService: EnterpriseService @Inject lateinit var pictureInPicturePresenter: PictureInPicturePresenter @Inject lateinit var buildMeta: BuildMeta @@ -114,6 +116,7 @@ class ElementCallActivity : }.collectAsState(SemanticColorsLightDark.default) ElementThemeApp( appPreferencesStore = appPreferencesStore, + featureFlagService = featureFlagService, compoundLight = colors.light, compoundDark = colors.dark, buildMeta = buildMeta, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt index 73233fe453..2c4deab65e 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallActivity.kt @@ -30,6 +30,7 @@ import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.designsystem.theme.ElementThemeApp import io.element.android.libraries.di.annotations.AppCoroutineScope +import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.preferences.api.store.AppPreferencesStore import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.filter @@ -57,6 +58,9 @@ class IncomingCallActivity : AppCompatActivity() { @Inject lateinit var appPreferencesStore: AppPreferencesStore + @Inject + lateinit var featureFlagService: FeatureFlagService + @Inject lateinit var enterpriseService: EnterpriseService @@ -88,6 +92,7 @@ class IncomingCallActivity : AppCompatActivity() { }.collectAsState(SemanticColorsLightDark.default) ElementThemeApp( appPreferencesStore = appPreferencesStore, + featureFlagService = featureFlagService, compoundLight = colors.light, compoundDark = colors.dark, buildMeta = buildMeta, diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt index 6209c19be2..34adfeca99 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt @@ -30,6 +30,7 @@ import io.element.android.features.lockscreen.impl.unlock.di.PinUnlockBindings import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.designsystem.theme.ElementThemeApp +import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.preferences.api.store.AppPreferencesStore import kotlinx.coroutines.launch @@ -43,6 +44,7 @@ class PinUnlockActivity : AppCompatActivity() { @Inject lateinit var presenter: PinUnlockPresenter @Inject lateinit var lockScreenService: LockScreenService @Inject lateinit var appPreferencesStore: AppPreferencesStore + @Inject lateinit var featureFlagService: FeatureFlagService @Inject lateinit var enterpriseService: EnterpriseService @Inject lateinit var buildMeta: BuildMeta @@ -56,6 +58,7 @@ class PinUnlockActivity : AppCompatActivity() { }.collectAsState(SemanticColorsLightDark.default) ElementThemeApp( appPreferencesStore = appPreferencesStore, + featureFlagService = featureFlagService, compoundLight = colors.light, compoundDark = colors.dark, buildMeta = buildMeta, 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 5f95806469..ae32bb01a5 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 @@ -23,6 +23,7 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags 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.flow.collect import kotlinx.coroutines.flow.combine @@ -45,8 +46,11 @@ class AdvancedSettingsPresenter( val isSharePresenceEnabled by remember { sessionPreferencesStore.isSharePresenceEnabled() }.collectAsState(initial = true) - val theme = remember { - appPreferencesStore.getThemeFlow().mapToTheme() + val isBlackThemeAllowed by remember { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.AllowBlackTheme) + }.collectAsState(initial = false) + val theme = remember(isBlackThemeAllowed) { + appPreferencesStore.getThemeFlow().mapToTheme(isBlackThemeAllowed) }.collectAsState(initial = Theme.System) val mediaPreviewConfigState = mediaPreviewConfigStateStore.state() @@ -66,6 +70,14 @@ class AdvancedSettingsPresenter( value = featureFlagService.isFeatureEnabled(FeatureFlags.SelectableMediaQuality) } + val availableThemeOptions = remember(isBlackThemeAllowed) { + if (isBlackThemeAllowed) { + ThemeOption.entries + } else { + ThemeOption.entries.filterNot { it == ThemeOption.Black } + }.toImmutableList() + } + val mediaOptimizationState by produceState(null) { val hasSplitMediaQualityOptionsFlow = featureFlagService.isFeatureEnabledFlow(FeatureFlags.SelectableMediaQuality) combine( @@ -119,6 +131,7 @@ class AdvancedSettingsPresenter( isSharePresenceEnabled = isSharePresenceEnabled, mediaOptimizationState = mediaOptimizationState, theme = themeOption, + availableThemeOptions = availableThemeOptions, mediaPreviewConfigState = mediaPreviewConfigState, 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 7cb9e9ce86..0525130048 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 @@ -14,12 +14,14 @@ import androidx.compose.ui.res.stringResource 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( val isDeveloperModeEnabled: Boolean, val isSharePresenceEnabled: Boolean, val mediaOptimizationState: MediaOptimizationState?, val theme: ThemeOption, + val availableThemeOptions: ImmutableList, val mediaPreviewConfigState: MediaPreviewConfigState, val eventSink: (AdvancedSettingsEvents) -> Unit ) 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 6cbe6e5c51..87df614074 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 @@ -12,6 +12,8 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.media.MediaPreviewValue import io.element.android.libraries.preferences.api.store.VideoCompressionPreset +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList open class AdvancedSettingsStateProvider : PreviewParameterProvider { override val values: Sequence @@ -36,6 +38,7 @@ fun aAdvancedSettingsState( isSharePresenceEnabled: Boolean = false, mediaOptimizationState: MediaOptimizationState = MediaOptimizationState.AllMedia(isEnabled = false), theme: ThemeOption = ThemeOption.System, + availableThemeOptions: ImmutableList = ThemeOption.entries.toImmutableList(), hideInviteAvatars: Boolean = false, timelineMediaPreviewValue: MediaPreviewValue = MediaPreviewValue.On, setTimelineMediaPreviewAction: AsyncAction = AsyncAction.Uninitialized, @@ -46,6 +49,7 @@ fun aAdvancedSettingsState( isSharePresenceEnabled = isSharePresenceEnabled, mediaOptimizationState = mediaOptimizationState, theme = theme, + availableThemeOptions = availableThemeOptions, mediaPreviewConfigState = MediaPreviewConfigState( hideInviteAvatars = hideInviteAvatars, timelineMediaPreviewValue = timelineMediaPreviewValue, 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 2e4d6f9ce5..230f5fa739 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 @@ -47,7 +47,6 @@ 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 kotlinx.collections.immutable.toImmutableList @Composable fun AdvancedSettingsView( @@ -75,7 +74,7 @@ fun AdvancedSettingsView( PreferenceDropdown( title = stringResource(id = CommonStrings.common_appearance), selectedOption = state.theme, - options = ThemeOption.entries.toImmutableList(), + options = state.availableThemeOptions, onSelectOption = { themeOption -> state.eventSink(AdvancedSettingsEvents.SetTheme(themeOption)) } 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 942d549dab..fe121e4fe9 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 @@ -12,6 +12,7 @@ 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.compound.theme.Theme import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService @@ -20,6 +21,7 @@ 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 import io.element.android.tests.testutils.WarmUpRule +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -40,6 +42,9 @@ class AdvancedSettingsPresenterTest { assertThat(isSharePresenceEnabled).isTrue() assertThat(mediaOptimizationState).isNull() assertThat(theme).isEqualTo(ThemeOption.System) + assertThat(availableThemeOptions).isEqualTo( + listOf(ThemeOption.System, ThemeOption.Light, ThemeOption.Dark).toImmutableList() + ) assertThat(mediaPreviewConfigState.hideInviteAvatars).isFalse() assertThat(mediaPreviewConfigState.timelineMediaPreviewValue).isEqualTo(MediaPreviewValue.On) assertThat(mediaPreviewConfigState.setHideInviteAvatarsAction).isEqualTo(AsyncAction.Uninitialized) @@ -204,6 +209,42 @@ class AdvancedSettingsPresenterTest { } } + @Test + fun `present - black theme option shown when feature flag enabled`() = runTest { + val presenter = createAdvancedSettingsPresenter( + featureFlagService = FakeFeatureFlagService().apply { + setFeatureEnabled(FeatureFlags.AllowBlackTheme, true) + } + ) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + + with(awaitItem()) { + assertThat(availableThemeOptions).contains(ThemeOption.Black) + assertThat(availableThemeOptions).isEqualTo(ThemeOption.entries.toImmutableList()) + } + } + } + + @Test + fun `present - stored black theme falls back to dark when feature flag disabled`() = runTest { + val appPreferencesStore = InMemoryAppPreferencesStore().apply { + setTheme(Theme.Black.name) + } + val presenter = createAdvancedSettingsPresenter(appPreferencesStore = appPreferencesStore) + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + skipItems(1) + + with(awaitItem()) { + assertThat(theme).isEqualTo(ThemeOption.Dark) + } + } + } + @Test fun `present - hide invite avatars`() = runTest { val mediaPreviewStore = FakeMediaPreviewConfigStateStore() 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 36fd30983e..e46e350415 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 @@ -12,6 +12,7 @@ import androidx.activity.ComponentActivity import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.Interaction @@ -24,9 +25,11 @@ import io.element.android.services.analytics.compose.LocalAnalyticsService import io.element.android.services.analytics.test.FakeAnalyticsService import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.assertNoNodeWithText import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack +import kotlinx.collections.immutable.toImmutableList import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule @@ -65,6 +68,31 @@ class AdvancedSettingsViewTest { eventsRecorder.assertSingle(AdvancedSettingsEvents.SetTheme(ThemeOption.Dark)) } + @Test + fun `black theme is shown when available`() { + rule.setAdvancedSettingsView( + state = aAdvancedSettingsState( + availableThemeOptions = ThemeOption.entries.toImmutableList(), + ), + ) + rule.clickOn(CommonStrings.common_appearance) + rule.run { + val text = activity.getString(CommonStrings.common_black) + onNodeWithText(text).assertExists() + } + } + + @Test + fun `black theme is hidden when unavailable`() { + rule.setAdvancedSettingsView( + state = aAdvancedSettingsState( + availableThemeOptions = ThemeOption.entries.filterNot { it == ThemeOption.Black }.toImmutableList(), + ), + ) + rule.clickOn(CommonStrings.common_appearance) + rule.assertNoNodeWithText(CommonStrings.common_black) + } + @Test fun `clicking on View source emits the expected event`() { val eventsRecorder = EventsRecorder() diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt index fd00abb4f4..04cb90b746 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt @@ -20,6 +20,10 @@ enum class Theme { Light, } +private fun Theme.coerceBlackTheme(allowBlackTheme: Boolean): Theme { + return if (this == Theme.Black && !allowBlackTheme) Theme.Dark else this +} + @Composable fun Theme.isDark(): Boolean { return when (this) { @@ -29,9 +33,9 @@ fun Theme.isDark(): Boolean { } } -fun Flow.mapToTheme(): Flow = map { +fun Flow.mapToTheme(allowBlackTheme: Boolean = true): Flow = map { when (it) { null -> Theme.System else -> Theme.valueOf(it) - } + }.coerceBlackTheme(allowBlackTheme) } diff --git a/libraries/compound/src/test/kotlin/io/element/android/compound/theme/ThemeTest.kt b/libraries/compound/src/test/kotlin/io/element/android/compound/theme/ThemeTest.kt index 8fd7c5f041..3f43cfea67 100644 --- a/libraries/compound/src/test/kotlin/io/element/android/compound/theme/ThemeTest.kt +++ b/libraries/compound/src/test/kotlin/io/element/android/compound/theme/ThemeTest.kt @@ -15,6 +15,7 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Test @@ -72,4 +73,14 @@ class ThemeTest { assertThat(awaitItem()).isTrue() } } + + @Test + fun `mapToTheme falls back to dark when black theme is disabled`() = runTest { + flowOf(Theme.Black.name) + .mapToTheme(allowBlackTheme = false) + .test { + assertThat(awaitItem()).isEqualTo(Theme.Dark) + awaitComplete() + } + } } diff --git a/libraries/designsystem/build.gradle.kts b/libraries/designsystem/build.gradle.kts index bdb9a32e89..c159659fb0 100644 --- a/libraries/designsystem/build.gradle.kts +++ b/libraries/designsystem/build.gradle.kts @@ -38,6 +38,7 @@ dependencies { implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) implementation(projects.libraries.core) + implementation(projects.libraries.featureflag.api) implementation(projects.libraries.preferences.api) implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt index a7bd12bc13..c0700620bc 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt @@ -22,6 +22,8 @@ import io.element.android.compound.theme.mapToTheme import io.element.android.compound.tokens.generated.SemanticColors import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.preferences.api.store.AppPreferencesStore val LocalBuildMeta = staticCompositionLocalOf { @@ -53,15 +55,18 @@ val LocalBuildMeta = staticCompositionLocalOf { @Composable fun ElementThemeApp( appPreferencesStore: AppPreferencesStore, + featureFlagService: FeatureFlagService, compoundLight: SemanticColors, compoundDark: SemanticColors, buildMeta: BuildMeta, content: @Composable () -> Unit, ) { + val isBlackThemeAllowed by remember { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.AllowBlackTheme) + }.collectAsState(initial = false) val theme by remember { - appPreferencesStore.getThemeFlow().mapToTheme() - } - .collectAsState(initial = Theme.System) + appPreferencesStore.getThemeFlow().mapToTheme(allowBlackTheme = isBlackThemeAllowed) + }.collectAsState(initial = Theme.System) LaunchedEffect(theme) { AppCompatDelegate.setDefaultNightMode( when (theme) { 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 6cd9dec60c..40e99fa07f 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 @@ -147,6 +147,13 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), + AllowBlackTheme( + key = "feature.allow_black_theme", + title = "Allow black theme", + description = "Allow selecting the black appearance theme for battery saving on OLED.", + defaultValue = { false }, + isFinished = false, + ), LiveLocationSharing( key = "feature.liveLocationSharing", title = "Live location sharing", From 43bef7f1df6ac3e5aee86b1f4ddddfcbf70f9272 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Sun, 5 Apr 2026 12:34:07 +0400 Subject: [PATCH 16/44] Add isBlackThemeAllowed as a key to theme remember block --- .../android/libraries/designsystem/theme/ElementThemeApp.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt index c0700620bc..0c2fdff0ab 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/ElementThemeApp.kt @@ -64,7 +64,7 @@ fun ElementThemeApp( val isBlackThemeAllowed by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.AllowBlackTheme) }.collectAsState(initial = false) - val theme by remember { + val theme by remember(isBlackThemeAllowed) { appPreferencesStore.getThemeFlow().mapToTheme(allowBlackTheme = isBlackThemeAllowed) }.collectAsState(initial = Theme.System) LaunchedEffect(theme) { From fd92a2eef25d4b90ce749b054fa2f6230bc8f581 Mon Sep 17 00:00:00 2001 From: Timur Gilfanov Date: Sun, 5 Apr 2026 12:34:25 +0400 Subject: [PATCH 17/44] Remove default value for `allowBlackTheme` in `mapToTheme` --- .../src/main/kotlin/io/element/android/compound/theme/Theme.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt index 04cb90b746..bf5932da59 100644 --- a/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt +++ b/libraries/compound/src/main/kotlin/io/element/android/compound/theme/Theme.kt @@ -33,7 +33,7 @@ fun Theme.isDark(): Boolean { } } -fun Flow.mapToTheme(allowBlackTheme: Boolean = true): Flow = map { +fun Flow.mapToTheme(allowBlackTheme: Boolean): Flow = map { when (it) { null -> Theme.System else -> Theme.valueOf(it) From 9ba8798175e8ec8e812baf5a316207d594f1d8f2 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Apr 2026 14:43:24 +0200 Subject: [PATCH 18/44] Refactor LiveLocationShare to include structured LastLocation --- .../location/impl/show/ShowLocationPresenter.kt | 5 +++-- .../api/room/location/LiveLocationShare.kt | 17 +++++++++++++---- .../room/location/LiveLocationSharesFlow.kt | 13 ++++++++++--- 3 files changed, 26 insertions(+), 9 deletions(-) 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 b72c01e697..90796da4ca 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 @@ -138,7 +138,8 @@ class ShowLocationPresenter( val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() } combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members -> liveShares.mapNotNull { share -> - val location = Location.fromGeoUri(share.lastGeoUri) ?: return@mapNotNull null + val lastLocation = share.lastLocation ?: return@mapNotNull null + val location = Location.fromGeoUri(lastLocation.geoUri) ?: return@mapNotNull null val member = members.find { it.userId == share.userId } val displayName = member?.getBestName() ?: share.userId.value val avatarUrl = member?.avatarUrl @@ -154,7 +155,7 @@ class ShowLocationPresenter( formattedTimestamp = "Sharing live location", location = location, isLive = true, - assetType = AssetType.SENDER, + assetType = lastLocation.assetType, ) }.toPersistentList() }.collect { value = it } 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 5f9cd41462..59b2381dbf 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 @@ -15,8 +15,17 @@ import io.element.android.libraries.matrix.api.core.UserId data class LiveLocationShare( /** The user who is sharing their location. */ val userId: UserId, - /** The last known geo URI (e.g., "geo:51.5074,-0.1278"). */ - val lastGeoUri: String, - /** The timestamp of the last location update. */ - val lastTimestamp: Long, + /** The last known location if any. */ + val lastLocation: LastLocation?, + /** The timestamp when location sharing ends, in milliseconds. */ + val endTimestamp: Long, +) + +data class LastLocation( + /** The last known geo URI (e.g., "geo:51.5074,-0.1278"). */ + val geoUri: String, + /** The timestamp of the last location update. */ + val timestamp: Long, + /** The asset of the last location update. */ + val assetType: AssetType, ) 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 7b3a29cf4a..efe2d0cd68 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 @@ -8,15 +8,16 @@ package io.element.android.libraries.matrix.impl.room.location 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 import io.element.android.libraries.matrix.impl.util.mxCallbackFlow import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.buffer -import org.matrix.rustcomponents.sdk.LiveLocationShare as RustLiveLocationShare import org.matrix.rustcomponents.sdk.LiveLocationShareListener import org.matrix.rustcomponents.sdk.LiveLocationShareUpdate import org.matrix.rustcomponents.sdk.RoomInterface +import org.matrix.rustcomponents.sdk.LiveLocationShare as RustLiveLocationShare fun RoomInterface.liveLocationSharesFlow(): Flow> { fun MutableList.applyUpdate(update: LiveLocationShareUpdate) { @@ -53,8 +54,14 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { private fun RustLiveLocationShare.into(): LiveLocationShare { return LiveLocationShare( userId = UserId(userId), - lastGeoUri = lastLocation?.location?.geoUri.orEmpty(), - lastTimestamp = lastLocation?.ts?.toLong() ?: 0, + lastLocation = lastLocation?.let { + LastLocation( + geoUri = it.location.geoUri, + timestamp = it.ts.toLong(), + assetType = it.location.asset.into(), + ) + }, + endTimestamp = (startTs + timeout).toLong() ) } From 7c3b9523df00e09fac5c6c3d9e9421590c5ca276 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Apr 2026 20:44:05 +0200 Subject: [PATCH 19/44] Improve live location UI with empty state --- .../impl/common/ui/LocationShareRow.kt | 6 +- .../impl/show/ShowLocationPresenter.kt | 6 +- .../location/impl/show/ShowLocationState.kt | 6 +- .../impl/show/ShowLocationStateProvider.kt | 9 ++- .../location/impl/show/ShowLocationView.kt | 62 ++++++++++++------- 5 files changed, 56 insertions(+), 33 deletions(-) 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 b949f55c76..866c7342ca 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 @@ -91,7 +91,7 @@ fun LocationShareRow( ) } Text( - text = item.formattedTimestamp, + text = item.description, style = ElementTheme.typography.fontBodySmRegular, color = ElementTheme.colors.textSecondary, maxLines = 1, @@ -123,7 +123,7 @@ internal fun LocationShareRowPreview() = ElementPreview { url = null, size = AvatarSize.UserListItem, ), - formattedTimestamp = "Shared 1 min ago", + description = "Shared 1 min ago", isLive = true, assetType = AssetType.SENDER, location = Location(0.0, 0.0) @@ -142,7 +142,7 @@ internal fun LocationShareRowPreview() = ElementPreview { ), isLive = false, assetType = AssetType.PIN, - formattedTimestamp = "Shared 5 hours ago", + description = "Shared 5 hours ago", location = Location(0.0, 0.0) ), onShareClick = {}, 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 90796da4ca..c46805684e 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 @@ -40,7 +40,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.matrix.api.room.getBestName import io.element.android.libraries.matrix.api.room.joinedRoomMembers -import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.collections.immutable.persistentListOf @@ -124,7 +123,7 @@ class ShowLocationPresenter( url = mode.senderAvatarUrl, size = AvatarSize.UserListItem, ), - formattedTimestamp = formattedTimestamp, + description = formattedTimestamp, location = mode.location, isLive = false, assetType = mode.assetType, @@ -152,7 +151,7 @@ class ShowLocationPresenter( url = avatarUrl, size = AvatarSize.UserListItem, ), - formattedTimestamp = "Sharing live location", + description = "Sharing live location", location = location, isLive = true, assetType = lastLocation.assetType, @@ -169,6 +168,7 @@ class ShowLocationPresenter( locationShares = locationShares, hasLocationPermission = permissionsState.isAnyGranted, isTrackMyLocation = isTrackMyLocation, + isLive = mode is ShowLocationMode.Live, appName = appName, eventSink = ::handleEvent, ) 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 9494db12ec..24090a1504 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 @@ -9,6 +9,7 @@ package io.element.android.features.location.impl.show import io.element.android.features.location.api.Location +import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.features.location.impl.common.ui.LocationMarkerData import io.element.android.libraries.designsystem.components.PinVariant @@ -18,6 +19,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType import kotlinx.collections.immutable.ImmutableList data class ShowLocationState( + val isLive: Boolean, val dialogState: LocationConstraintsDialogState, val locationShares: ImmutableList, val hasLocationPermission: Boolean, @@ -25,14 +27,14 @@ data class ShowLocationState( val appName: String, val eventSink: (ShowLocationEvent) -> Unit, ) { - val isSheetDraggable = locationShares.any { item -> item.isLive } + val isSheetDraggable = isLive && locationShares.isNotEmpty() } data class LocationShareItem( val userId: UserId, val displayName: String, val avatarData: AvatarData, - val formattedTimestamp: String, + val description: String, val location: Location, val isLive: Boolean, val assetType: AssetType?, 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 8bee410715..774a97d284 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 @@ -10,6 +10,7 @@ package io.element.android.features.location.impl.show import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.api.Location +import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -21,6 +22,8 @@ class ShowLocationStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( aShowLocationState(), + aShowLocationState(isLive = true), + aShowLocationState(isLive = true, locationShares = emptyList()), aShowLocationState( constraintsDialogState = LocationConstraintsDialogState.PermissionDenied, ), @@ -44,8 +47,9 @@ class ShowLocationStateProvider : PreviewParameterProvider { private const val APP_NAME = "ApplicationName" fun aShowLocationState( + isLive: Boolean = false, constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None, - locationShares: List = listOf(aLocationShareItem()), + locationShares: List = listOf(aLocationShareItem(isLive = isLive)), hasLocationPermission: Boolean = false, isTrackMyLocation: Boolean = false, appName: String = APP_NAME, @@ -57,6 +61,7 @@ fun aShowLocationState( hasLocationPermission = hasLocationPermission, isTrackMyLocation = isTrackMyLocation, appName = appName, + isLive = isLive, eventSink = eventSink, ) } @@ -78,7 +83,7 @@ fun aLocationShareItem( userId = userId, displayName = displayName, avatarData = avatarData, - formattedTimestamp = formattedTimestamp, + description = formattedTimestamp, location = location, isLive = isLive, assetType = assetType, 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 ad2d4cb8ca..30bb027bb5 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 @@ -12,6 +12,7 @@ package io.element.android.features.location.impl.show import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.BottomSheetDefaults @@ -26,6 +27,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -88,7 +90,7 @@ fun ShowLocationView( bottomSheetState = rememberStandardBottomSheetState( initialValue = if (state.isSheetDraggable) { - SheetValue.PartiallyExpanded + SheetValue.Expanded } else { SheetValue.Expanded } @@ -116,29 +118,43 @@ fun ShowLocationView( }, sheetContent = { sheetPaddings -> val coroutineScope = rememberCoroutineScope() - Spacer(Modifier.height(20.dp)) - Text( - text = stringResource(CommonStrings.screen_static_location_sheet_title), - style = ElementTheme.typography.fontBodyLgMedium, - color = ElementTheme.colors.textPrimary, - modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), - ) - state.locationShares.forEach { locationShare -> - LocationShareRow( - item = locationShare, - onShareClick = { state.eventSink(ShowLocationEvent.Share(locationShare.location)) }, - modifier = Modifier.clickable { - state.eventSink(ShowLocationEvent.TrackMyLocation(false)) - val position = CameraPosition( - padding = sheetPaddings, - target = Position(locationShare.location.lon, locationShare.location.lat), - zoom = MapDefaults.DEFAULT_ZOOM - ) - coroutineScope.launch { - cameraState.animateTo(finalPosition = position) - } - } + if (!state.isSheetDraggable) { + Spacer(Modifier.height(20.dp)) + } + if (state.locationShares.isEmpty()) { + Spacer(Modifier.height(16.dp)) + Text( + text = "Nobody is sharing their location", + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + textAlign = TextAlign.Center, ) + Spacer(Modifier.height(16.dp)) + } else { + Text( + text = stringResource(CommonStrings.screen_static_location_sheet_title), + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), + ) + state.locationShares.forEach { locationShare -> + LocationShareRow( + item = locationShare, + onShareClick = { state.eventSink(ShowLocationEvent.Share(locationShare.location)) }, + modifier = Modifier.clickable { + state.eventSink(ShowLocationEvent.TrackMyLocation(false)) + val position = CameraPosition( + padding = sheetPaddings, + target = Position(locationShare.location.lon, locationShare.location.lat), + zoom = MapDefaults.DEFAULT_ZOOM + ) + coroutineScope.launch { + cameraState.animateTo(finalPosition = position) + } + } + ) + } } }, mapContent = { From 0e9af5f42a5bbfc5f57870f7976f1d8b4305e818 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Apr 2026 20:45:18 +0200 Subject: [PATCH 20/44] Refactor live location shares to use callbackFlow --- .../impl/room/location/LiveLocationSharesFlow.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) 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 efe2d0cd68..4f4ddac667 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 @@ -10,10 +10,12 @@ package io.element.android.libraries.matrix.impl.room.location 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 -import io.element.android.libraries.matrix.impl.util.mxCallbackFlow +import io.element.android.libraries.matrix.impl.util.cancelAndDestroy import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.buffer +import kotlinx.coroutines.flow.callbackFlow import org.matrix.rustcomponents.sdk.LiveLocationShareListener import org.matrix.rustcomponents.sdk.LiveLocationShareUpdate import org.matrix.rustcomponents.sdk.RoomInterface @@ -38,9 +40,10 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { is LiveLocationShareUpdate.Truncate -> subList(update.length.toInt(), size).clear() } } - return mxCallbackFlow { + return callbackFlow { + val liveLocationShares = liveLocationShares() val shares: MutableList = ArrayList() - subscribeToLiveLocationShares(object : LiveLocationShareListener { + val taskHandle = liveLocationShares.subscribe(object : LiveLocationShareListener { override fun onUpdate(updates: List) { for (update in updates) { shares.applyUpdate(update) @@ -48,6 +51,10 @@ fun RoomInterface.liveLocationSharesFlow(): Flow> { trySend(shares) } }) + awaitClose { + taskHandle.cancelAndDestroy() + liveLocationShares.destroy() + } }.buffer(Channel.UNLIMITED) } From 537063d899ce2577147798c7c7eb7bc2312d6de1 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 10 Apr 2026 21:11:30 +0200 Subject: [PATCH 21/44] Add focused location tracking when opening the map --- .../features/location/api/ShowLocationMode.kt | 4 +++- .../impl/show/ShowLocationPresenter.kt | 13 ++++++++---- .../location/impl/show/ShowLocationState.kt | 2 +- .../impl/show/ShowLocationStateProvider.kt | 2 ++ .../location/impl/show/ShowLocationView.kt | 21 +++++++++++-------- .../messages/impl/MessagesFlowNode.kt | 2 +- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/ShowLocationMode.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/ShowLocationMode.kt index 1227ddec46..3feeeff57d 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/ShowLocationMode.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/ShowLocationMode.kt @@ -24,5 +24,7 @@ sealed interface ShowLocationMode : Parcelable { ) : ShowLocationMode @Parcelize - data object Live : ShowLocationMode + data class Live( + val senderId: UserId + ) : ShowLocationMode } 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 c46805684e..2f9c3d0d81 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 @@ -131,8 +131,8 @@ class ShowLocationPresenter( ) } } - ShowLocationMode.Live -> { - val liveShares by produceState(persistentListOf()) { + is ShowLocationMode.Live -> { + produceState(persistentListOf()) { val liveLocationSharesFlow = joinedRoom.subscribeToLiveLocationShares() val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() } combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members -> @@ -158,14 +158,19 @@ class ShowLocationPresenter( ) }.toPersistentList() }.collect { value = it } - } - liveShares + }.value } } + val focusedLocation = when (mode) { + is ShowLocationMode.Static -> locationShares.firstOrNull() + is ShowLocationMode.Live -> locationShares.firstOrNull { it.userId == mode.senderId } + } + return ShowLocationState( dialogState = dialogState, locationShares = locationShares, + focusedLocation = focusedLocation, hasLocationPermission = permissionsState.isAnyGranted, isTrackMyLocation = isTrackMyLocation, isLive = mode is ShowLocationMode.Live, 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 24090a1504..3d4df465f9 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 @@ -9,7 +9,6 @@ package io.element.android.features.location.impl.show import io.element.android.features.location.api.Location -import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.features.location.impl.common.ui.LocationMarkerData import io.element.android.libraries.designsystem.components.PinVariant @@ -22,6 +21,7 @@ data class ShowLocationState( val isLive: Boolean, val dialogState: LocationConstraintsDialogState, val locationShares: ImmutableList, + val focusedLocation: LocationShareItem?, val hasLocationPermission: Boolean, val isTrackMyLocation: Boolean, val appName: String, 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 774a97d284..3b08e81890 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 @@ -50,6 +50,7 @@ fun aShowLocationState( isLive: Boolean = false, constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None, locationShares: List = listOf(aLocationShareItem(isLive = isLive)), + focusedLocation: LocationShareItem? = locationShares.firstOrNull(), hasLocationPermission: Boolean = false, isTrackMyLocation: Boolean = false, appName: String = APP_NAME, @@ -58,6 +59,7 @@ fun aShowLocationState( return ShowLocationState( dialogState = constraintsDialogState, locationShares = locationShares.toImmutableList(), + focusedLocation = focusedLocation, hasLocationPermission = hasLocationPermission, isTrackMyLocation = isTrackMyLocation, appName = appName, 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 30bb027bb5..de35430b39 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 @@ -22,8 +22,11 @@ import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.material3.rememberStandardBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -67,25 +70,25 @@ fun ShowLocationView( onDismiss = { state.eventSink(ShowLocationEvent.DismissDialog) }, ) - val initialPosition = remember { - if (state.locationShares.isEmpty()) { - MapDefaults.defaultCameraPosition - } else { - val firstLocation = state.locationShares.first().location - CameraPosition( - target = Position(latitude = firstLocation.lat, longitude = firstLocation.lon), + val cameraState = rememberCameraState(firstPosition = MapDefaults.defaultCameraPosition) + var hasAnimatedToFocusedLocation by remember { mutableStateOf(false) } + LaunchedEffect(state.focusedLocation) { + if (state.focusedLocation != null && !hasAnimatedToFocusedLocation) { + hasAnimatedToFocusedLocation = true + val position = CameraPosition( + target = Position(latitude = state.focusedLocation.location.lat, longitude = state.focusedLocation.location.lon), zoom = MapDefaults.DEFAULT_ZOOM ) + cameraState.position = position } } - val cameraState = rememberCameraState(firstPosition = initialPosition) - val userLocationState = rememberUserLocationState(state.hasLocationPermission) LaunchedEffect(cameraState.isCameraMoving) { if (cameraState.moveReason == CameraMoveReason.GESTURE) { state.eventSink(ShowLocationEvent.TrackMyLocation(false)) } } + val userLocationState = rememberUserLocationState(state.hasLocationPermission) val scaffoldState = rememberBottomSheetScaffoldState( bottomSheetState = rememberStandardBottomSheetState( initialValue = 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 dc0ade0dc2..5affdb4484 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 @@ -571,7 +571,7 @@ class MessagesFlowNode( } is TimelineItemLocationContent -> { val mode = when(event.content.mode){ - is TimelineItemLocationContent.Mode.Live -> ShowLocationMode.Live + is TimelineItemLocationContent.Mode.Live -> ShowLocationMode.Live(event.senderId) is TimelineItemLocationContent.Mode.Static -> ShowLocationMode.Static( location = event.content.mode.location, senderName = event.safeSenderName, From 580e85d232de5287cf6acd9643ad1cfb9fdb0e62 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 13 Apr 2026 11:51:48 +0200 Subject: [PATCH 22/44] Fix live location share item description --- .../features/location/impl/common/ui/LocationShareRow.kt | 8 ++++---- .../features/location/impl/show/ShowLocationPresenter.kt | 9 +++++++-- .../features/location/impl/show/ShowLocationState.kt | 2 +- .../location/impl/show/ShowLocationStateProvider.kt | 7 +++---- 4 files changed, 15 insertions(+), 11 deletions(-) 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 866c7342ca..6fbcfc4814 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 @@ -91,9 +91,9 @@ fun LocationShareRow( ) } Text( - text = item.description, + text = if (item.isLive) "Sharing live location" else item.formattedTimestamp, style = ElementTheme.typography.fontBodySmRegular, - color = ElementTheme.colors.textSecondary, + color = if(item.isLive) ElementTheme.colors.textPrimary else ElementTheme.colors.textSecondary, maxLines = 1, overflow = TextOverflow.Ellipsis, ) @@ -123,7 +123,7 @@ internal fun LocationShareRowPreview() = ElementPreview { url = null, size = AvatarSize.UserListItem, ), - description = "Shared 1 min ago", + formattedTimestamp = "Shared 1 min ago", isLive = true, assetType = AssetType.SENDER, location = Location(0.0, 0.0) @@ -142,7 +142,7 @@ internal fun LocationShareRowPreview() = ElementPreview { ), isLive = false, assetType = AssetType.PIN, - description = "Shared 5 hours ago", + formattedTimestamp = "Shared 5 hours ago", location = Location(0.0, 0.0) ), onShareClick = {}, 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 2f9c3d0d81..e23baf1a43 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 @@ -123,7 +123,7 @@ class ShowLocationPresenter( url = mode.senderAvatarUrl, size = AvatarSize.UserListItem, ), - description = formattedTimestamp, + formattedTimestamp = formattedTimestamp, location = mode.location, isLive = false, assetType = mode.assetType, @@ -142,6 +142,11 @@ class ShowLocationPresenter( val member = members.find { it.userId == share.userId } val displayName = member?.getBestName() ?: share.userId.value val avatarUrl = member?.avatarUrl + val relativeTime = dateFormatter.format(timestamp = share.lastLocation?.timestamp, mode = DateFormatterMode.Full, useRelative = true) + val formattedTimestamp = stringProvider.getString( + CommonStrings.screen_static_location_sheet_timestamp_description, + relativeTime + ) LocationShareItem( userId = share.userId, displayName = displayName, @@ -151,7 +156,7 @@ class ShowLocationPresenter( url = avatarUrl, size = AvatarSize.UserListItem, ), - description = "Sharing live location", + formattedTimestamp = formattedTimestamp, location = location, isLive = true, assetType = lastLocation.assetType, 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 3d4df465f9..b6a60f35db 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 @@ -34,7 +34,7 @@ data class LocationShareItem( val userId: UserId, val displayName: String, val avatarData: AvatarData, - val description: String, + val formattedTimestamp: String, val location: Location, val isLive: Boolean, val assetType: AssetType?, 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 3b08e81890..1ab2310365 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 @@ -10,7 +10,6 @@ package io.element.android.features.location.impl.show import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.api.Location -import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize @@ -77,15 +76,15 @@ fun aLocationShareItem( url = null, size = AvatarSize.UserListItem, ), - formattedTimestamp: String = "Shared 1 min ago", - location: Location = Location(1.23, 2.34, 4f), isLive: Boolean = false, assetType: AssetType? = null, + formattedTimestamp: String = "Shared 1 min ago", + location: Location = Location(1.23, 2.34, 4f), ) = LocationShareItem( userId = userId, displayName = displayName, avatarData = avatarData, - description = formattedTimestamp, + formattedTimestamp = formattedTimestamp, location = location, isLive = isLive, assetType = assetType, From f5683f9c8b5e753e47fefc19563b142737be0e0e Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Apr 2026 13:46:31 +0200 Subject: [PATCH 23/44] Improve live location bottomsheet interaction with map --- .../impl/common/ui/MapBottomSheetScaffold.kt | 10 +++- .../location/impl/show/ShowLocationView.kt | 55 ++++++++++--------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/MapBottomSheetScaffold.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/MapBottomSheetScaffold.kt index fbaed9c854..13c30c28eb 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/MapBottomSheetScaffold.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/ui/MapBottomSheetScaffold.kt @@ -10,12 +10,14 @@ package io.element.android.features.location.impl.common.ui import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.safeDrawing @@ -43,6 +45,7 @@ import androidx.compose.ui.unit.max import io.element.android.features.location.api.internal.rememberTileStyleUrl import io.element.android.features.location.impl.common.MapDefaults import io.element.android.libraries.core.data.tryOrNull +import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.theme.components.BottomSheetScaffold import org.maplibre.compose.camera.CameraState import org.maplibre.compose.camera.rememberCameraState @@ -112,8 +115,11 @@ fun MapBottomSheetScaffold( modifier = Modifier, sheetPeekHeight = sheetPeekHeight, sheetContent = { - sheetContent(sheetPadding) - Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)) + val maxContentHeight = (layoutHeightPx * 0.5f).roundToInt().toDp() + Column(modifier = Modifier.heightIn(max = maxContentHeight)) { + sheetContent(sheetPadding) + Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars)) + } }, scaffoldState = scaffoldState, sheetDragHandle = sheetDragHandle, 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 de35430b39..b660614ca2 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 @@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SheetValue @@ -90,15 +92,13 @@ fun ShowLocationView( val userLocationState = rememberUserLocationState(state.hasLocationPermission) val scaffoldState = rememberBottomSheetScaffoldState( - bottomSheetState = rememberStandardBottomSheetState( - initialValue = - if (state.isSheetDraggable) { - SheetValue.Expanded - } else { - SheetValue.Expanded - } - ) + bottomSheetState = rememberStandardBottomSheetState(SheetValue.Expanded) ) + LaunchedEffect(state.isSheetDraggable) { + if (!state.isSheetDraggable) { + scaffoldState.bottomSheetState.expand() + } + } MapBottomSheetScaffold( sheetDragHandle = if (state.isSheetDraggable) { { BottomSheetDefaults.DragHandle() } @@ -122,18 +122,19 @@ fun ShowLocationView( sheetContent = { sheetPaddings -> val coroutineScope = rememberCoroutineScope() if (!state.isSheetDraggable) { + // If sheet is draggable the DragHandle has already some padding Spacer(Modifier.height(20.dp)) } if (state.locationShares.isEmpty()) { - Spacer(Modifier.height(16.dp)) Text( text = "Nobody is sharing their location", style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textPrimary, - modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + modifier = Modifier + .fillMaxWidth() + .padding(all = 16.dp), textAlign = TextAlign.Center, ) - Spacer(Modifier.height(16.dp)) } else { Text( text = stringResource(CommonStrings.screen_static_location_sheet_title), @@ -141,22 +142,24 @@ fun ShowLocationView( color = ElementTheme.colors.textPrimary, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), ) - state.locationShares.forEach { locationShare -> - LocationShareRow( - item = locationShare, - onShareClick = { state.eventSink(ShowLocationEvent.Share(locationShare.location)) }, - modifier = Modifier.clickable { - state.eventSink(ShowLocationEvent.TrackMyLocation(false)) - val position = CameraPosition( - padding = sheetPaddings, - target = Position(locationShare.location.lon, locationShare.location.lat), - zoom = MapDefaults.DEFAULT_ZOOM - ) - coroutineScope.launch { - cameraState.animateTo(finalPosition = position) + LazyColumn { + items(state.locationShares) { locationShare -> + LocationShareRow( + item = locationShare, + onShareClick = { state.eventSink(ShowLocationEvent.Share(locationShare.location)) }, + modifier = Modifier.clickable { + state.eventSink(ShowLocationEvent.TrackMyLocation(false)) + val position = CameraPosition( + padding = sheetPaddings, + target = Position(locationShare.location.lon, locationShare.location.lat), + zoom = MapDefaults.DEFAULT_ZOOM + ) + coroutineScope.launch { + cameraState.animateTo(finalPosition = position) + } } - } - ) + ) + } } } }, From 11866afb03dbe197a46dddb8d682546afadc54a6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Apr 2026 13:55:54 +0200 Subject: [PATCH 24/44] Remove hardcoded strings --- .../features/location/impl/common/ui/LocationShareRow.kt | 2 +- .../android/features/location/impl/show/ShowLocationView.kt | 2 +- libraries/ui-strings/src/main/res/values/localazy.xml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) 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 6fbcfc4814..d2c7ba5966 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 @@ -91,7 +91,7 @@ fun LocationShareRow( ) } Text( - text = if (item.isLive) "Sharing live location" else item.formattedTimestamp, + text = if (item.isLive) stringResource(CommonStrings.screen_room_live_location_banner) else item.formattedTimestamp, style = ElementTheme.typography.fontBodySmRegular, color = if(item.isLive) ElementTheme.colors.textPrimary else ElementTheme.colors.textSecondary, maxLines = 1, 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 b660614ca2..7ac5946723 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 @@ -127,7 +127,7 @@ fun ShowLocationView( } if (state.locationShares.isEmpty()) { Text( - text = "Nobody is sharing their location", + text = stringResource(CommonStrings.screen_live_location_sheet_nobody_sharing), style = ElementTheme.typography.fontBodyLgMedium, color = ElementTheme.colors.textPrimary, modifier = Modifier diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index f91e3a85b0..d0ce3dce24 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -467,6 +467,7 @@ Are you sure you want to continue?" "Options" "Remove %1$s" "Settings" + "Nobody is sharing their location" "Failed selecting media, please try again." "Open Element Classic" "Open Element Classic on your device" From 67729f87c911bfc16279cfc8151f75e0d835df0b Mon Sep 17 00:00:00 2001 From: Gianluca Iavicoli Date: Wed, 15 Apr 2026 18:17:31 +0200 Subject: [PATCH 25/44] test: stabilize reply event ID test for voice message composer --- ...efaultVoiceMessageComposerPresenterTest.kt | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt index 5323ccd6f0..7d3b6cf647 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/voicemessages/composer/DefaultVoiceMessageComposerPresenterTest.kt @@ -414,23 +414,22 @@ class DefaultVoiceMessageComposerPresenterTest { fun `present - send voice message passes reply event ID only when in reply mode`() = runTest { val presenter = createDefaultVoiceMessageComposerPresenter() presenter.test { - // Send without reply - should pass null - messageComposerContext.composerMode = MessageComposerMode.Normal + // First send in Normal mode (default composerMode). awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Start)) awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Stop)) awaitItem().eventSink(VoiceMessageComposerEvent.SendVoiceMessage) - skipItems(1) // Sending state - advanceUntilIdle() + assertThat(awaitItem().voiceMessageState).isEqualTo(aPreviewState().toSendingState()) + val idleAfterFirstSend = awaitItem() + assertThat(idleAfterFirstSend.voiceMessageState).isEqualTo(VoiceMessageState.Idle) - sendVoiceMessageResult.assertions().isCalledOnce() - .with(any(), any(), any(), value(null)) - - // Send as reply - should pass event ID + // Switching to reply mode does not trigger recomposition, so reuse the prior eventSink. messageComposerContext.composerMode = aReplyMode() - awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Start)) + idleAfterFirstSend.eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Start)) awaitItem().eventSink(VoiceMessageComposerEvent.RecorderEvent(VoiceMessageRecorderEvent.Stop)) awaitItem().eventSink(VoiceMessageComposerEvent.SendVoiceMessage) - val finalState = awaitItem() // Sending state + assertThat(awaitItem().voiceMessageState).isEqualTo(aPreviewState().toSendingState()) + val finalState = awaitItem() + assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) sendVoiceMessageResult.assertions().isCalledExactly(2) .withSequence( From 704ddc9132e80d12050b9899f6963b65d862516b Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 15 Apr 2026 22:06:00 +0200 Subject: [PATCH 26/44] Update live location shares when reaching timeout (before actual stop event) --- .../impl/show/ShowLocationPresenter.kt | 2 +- .../impl/show/ShowLocationPresenterTest.kt | 76 ++++----- .../components/TimelineItemEventRow.kt | 9 +- .../event/TimelineItemEventContentView.kt | 13 +- .../event/TimelineItemLocationView.kt | 10 +- .../event/TimelineItemContentFactory.kt | 3 +- .../event/TimelineItemEventContentProvider.kt | 4 +- .../event/TimelineItemLocationContent.kt | 47 +++++- .../TimelineItemLocationContentProvider.kt | 4 + .../fixtures/TimelineItemsFactoryFixtures.kt | 3 + .../TimelineItemContentMessageFactoryTest.kt | 3 +- .../api/timeline/item/event/EventContent.kt | 4 +- .../matrix/impl/room/JoinedRustRoom.kt | 3 +- .../location/TimedLiveLocationSharesFlow.kt | 56 +++++++ .../item/event/TimelineEventContentMapper.kt | 2 +- .../TimedLiveLocationSharesFlowTest.kt | 148 ++++++++++++++++++ ...nticsNodeInteractionsProviderExtensions.kt | 8 + 17 files changed, 331 insertions(+), 64 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt 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 e23baf1a43..10501409fe 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 @@ -142,7 +142,7 @@ class ShowLocationPresenter( val member = members.find { it.userId == share.userId } val displayName = member?.getBestName() ?: share.userId.value val avatarUrl = member?.avatarUrl - val relativeTime = dateFormatter.format(timestamp = share.lastLocation?.timestamp, mode = DateFormatterMode.Full, useRelative = true) + val relativeTime = dateFormatter.format(timestamp = lastLocation.timestamp, mode = DateFormatterMode.Full, useRelative = true) val formattedTimestamp = stringProvider.getString( CommonStrings.screen_static_location_sheet_timestamp_description, relativeTime 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 81ec465686..c5120928dc 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 @@ -24,19 +24,21 @@ 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.FakeLiveLocationShareService import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +@OptIn(ExperimentalCoroutinesApi::class) class ShowLocationPresenterTest { @get:Rule val warmUpRule = WarmUpRule() @@ -330,7 +332,7 @@ class ShowLocationPresenterTest { @Test fun `live mode emits empty location shares initially`() = runTest { val presenter = createShowLocationPresenter( - mode = ShowLocationMode.Live, + mode = ShowLocationMode.Live(senderId = UserId("@alice:matrix.org")), joinedRoom = FakeJoinedRoom(), ) presenter.test { @@ -345,22 +347,13 @@ class ShowLocationPresenterTest { val userId = UserId("@bob:matrix.org") val liveSharesFlow = MutableStateFlow( listOf( - LiveLocationShare( - userId = userId, - lastGeoUri = "geo:48.8584,2.2945", - lastTimestamp = 1234567890L, - isLive = true, - ) - ) - ) - val fakeRoom = FakeJoinedRoom( - liveLocationShareService = FakeLiveLocationShareService( - liveLocationSharesFlow = liveSharesFlow + aLiveLocationShare(userId = userId) ) ) + val fakeRoom = FakeJoinedRoom(liveLocationSharesFlow = liveSharesFlow) val presenter = createShowLocationPresenter( - mode = ShowLocationMode.Live, + mode = ShowLocationMode.Live(senderId = userId), joinedRoom = fakeRoom, ) presenter.test { @@ -384,28 +377,14 @@ class ShowLocationPresenterTest { val invalidUserId = UserId("@bob:matrix.org") val liveSharesFlow = MutableStateFlow( listOf( - LiveLocationShare( - userId = validUserId, - lastGeoUri = "geo:48.8584,2.2945", - lastTimestamp = 1234567890L, - isLive = true, - ), - LiveLocationShare( - userId = invalidUserId, - lastGeoUri = "invalid-geo-uri", - lastTimestamp = 1234567890L, - isLive = true, - ), - ) - ) - val fakeRoom = FakeJoinedRoom( - liveLocationShareService = FakeLiveLocationShareService( - liveLocationSharesFlow = liveSharesFlow + aLiveLocationShare(userId = validUserId), + aLiveLocationShare(userId = invalidUserId, geoUri = "invalid-geo-uri"), ) ) + val fakeRoom = FakeJoinedRoom(liveLocationSharesFlow = liveSharesFlow) val presenter = createShowLocationPresenter( - mode = ShowLocationMode.Live, + mode = ShowLocationMode.Live(senderId = validUserId), joinedRoom = fakeRoom, ) presenter.test { @@ -423,14 +402,10 @@ class ShowLocationPresenterTest { fun `live mode updates when shares change`() = runTest { val userId = UserId("@bob:matrix.org") val liveSharesFlow = MutableStateFlow(emptyList()) - val fakeRoom = FakeJoinedRoom( - liveLocationShareService = FakeLiveLocationShareService( - liveLocationSharesFlow = liveSharesFlow - ) - ) + val fakeRoom = FakeJoinedRoom(liveLocationSharesFlow = liveSharesFlow) val presenter = createShowLocationPresenter( - mode = ShowLocationMode.Live, + mode = ShowLocationMode.Live(senderId = userId), joinedRoom = fakeRoom, ) presenter.test { @@ -440,12 +415,7 @@ class ShowLocationPresenterTest { // Emit a new live share liveSharesFlow.value = listOf( - LiveLocationShare( - userId = userId, - lastGeoUri = "geo:48.8584,2.2945", - lastTimestamp = 1234567890L, - isLive = true, - ) + aLiveLocationShare(userId = userId) ) val updatedState = awaitItem() @@ -494,3 +464,21 @@ class ShowLocationPresenterTest { } } } + +private fun aLiveLocationShare( + userId: UserId, + geoUri: String = "geo:48.8584,2.2945", + timestamp: Long = 1234567890L, + endTimestamp: Long = Long.MAX_VALUE, + assetType: AssetType = AssetType.SENDER, +): LiveLocationShare { + return LiveLocationShare( + userId = userId, + lastLocation = LastLocation( + geoUri = geoUri, + timestamp = timestamp, + assetType = assetType, + ), + endTimestamp = endTimestamp, + ) +} 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 b0b1e0c755..976fa3c17e 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 @@ -78,6 +78,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent +import io.element.android.features.messages.impl.timeline.model.event.ensureActiveLiveLocation import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionEvent import io.element.android.features.messages.impl.timeline.protection.TimelineProtectionState import io.element.android.features.messages.impl.timeline.protection.mustBeProtected @@ -777,7 +778,13 @@ private fun MessageEventBubbleContent( is TimelineItemImageContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Overlay is TimelineItemVideoContent -> if (content.showCaption) TimestampPosition.Aligned else TimestampPosition.Overlay is TimelineItemStickerContent -> TimestampPosition.Overlay - is TimelineItemLocationContent -> if (content.hideTimestamp) TimestampPosition.Hidden else TimestampPosition.Overlay + is TimelineItemLocationContent -> { + val content = content.ensureActiveLiveLocation() + val shouldHide = content.mode is TimelineItemLocationContent.Mode.Live && + content.mode.isActive && + content.mode.canStop + if (shouldHide) TimestampPosition.Hidden else TimestampPosition.Overlay + } is TimelineItemPollContent -> TimestampPosition.Below else -> TimestampPosition.Default } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt index 1de73f3658..2044796889 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt @@ -30,6 +30,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent 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.wysiwyg.link.Link @@ -71,11 +72,13 @@ fun TimelineItemEventContentView( onContentLayoutChange = onContentLayoutChange, modifier = modifier ) - is TimelineItemLocationContent -> TimelineItemLocationView( - content = content, - onStopLiveLocationClick = { eventSink(TimelineEvent.StopLiveLocationShare) }, - modifier = modifier - ) + is TimelineItemLocationContent -> { + TimelineItemLocationView( + content = content.ensureActiveLiveLocation(), + onStopLiveLocationClick = { eventSink(TimelineEvent.StopLiveLocationShare) }, + modifier = modifier + ) + } is TimelineItemImageContent -> TimelineItemImageView( content = content, hideMediaContent = hideMediaContent, 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 c9e3152afb..1c35216c38 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 @@ -25,6 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme @@ -32,12 +33,14 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.location.api.StaticMapView import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider +import io.element.android.features.messages.impl.timeline.model.event.ensureActiveLiveLocation import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.ui.strings.CommonStrings @Composable fun TimelineItemLocationView( @@ -121,7 +124,12 @@ private fun LiveLocationOverlay( Spacer(Modifier.width(8.dp)) Column(modifier = Modifier.weight(1f)) { Text( - text = if (mode.isActive) "Live location" else "Live location ended", + text = if (mode.isActive) { + stringResource(CommonStrings.common_live_location) + } else { + stringResource(CommonStrings.common_live_location_ended) + }, + style = ElementTheme.typography.fontBodySmMedium, color = ElementTheme.colors.textPrimary, ) 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 8b81ae0906..fcb346ecd7 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 @@ -111,7 +111,7 @@ class TimelineItemContentFactory( }.lastOrNull() val endsAt = dateFormatter.format( - timestamp = itemContent.endsAt, + timestamp = itemContent.endTimestamp, mode = DateFormatterMode.TimeOnly ) // Always create content, location can be null for "loading/waiting" state @@ -124,6 +124,7 @@ class TimelineItemContentFactory( lastKnownLocation = lastKnownLocation, isActive = itemContent.isLive, endsAt = stringProvider.getString(CommonStrings.common_ends_at, endsAt), + endTimestamp = itemContent.endTimestamp, ), ) } 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 9683a2c149..44dd2df38d 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 @@ -35,7 +35,9 @@ class TimelineItemEventContentProvider : PreviewParameterProvider mode.lastKnownLocation is Mode.Static -> mode.location @@ -71,7 +71,8 @@ data class TimelineItemLocationContent( val lastKnownLocation: Location?, val isActive: Boolean, val endsAt: String, - val canStop: Boolean = false + val endTimestamp: Long, + val canStop: Boolean = false, ) : Mode { val isLoading = lastKnownLocation == null && isActive } @@ -79,3 +80,41 @@ data class TimelineItemLocationContent( override val type: String = "TimelineItemLocationContent" } + +/** + * Overrides the isActive value if needed, to make sure endTimestamp is used in absence of stop event. + */ +@Composable +internal fun TimelineItemLocationContent.ensureActiveLiveLocation( + currentTimeMillis: () -> Long = System::currentTimeMillis, +): TimelineItemLocationContent { + return when (val mode = mode) { + is TimelineItemLocationContent.Mode.Live -> { + val isActive = rememberIsLiveLocationActive(mode, currentTimeMillis) + copy(mode = mode.copy(isActive = isActive)) + } + is TimelineItemLocationContent.Mode.Static -> this + } +} + +@Composable +private fun rememberIsLiveLocationActive( + mode: TimelineItemLocationContent.Mode.Live, + currentTimeMillis: () -> Long, +): Boolean { + + fun TimelineItemLocationContent.Mode.Live.isActive(): Boolean { + return isActive && endTimestamp > currentTimeMillis() + } + return produceState( + initialValue = mode.isActive(), + key1 = mode.endTimestamp, + key2 = mode.isActive, + ) { + if (mode.isActive) { + val remainingMillis = mode.endTimestamp - currentTimeMillis() + delay(remainingMillis) + } + value = false + }.value +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt index e2309c2210..a9cc9e59d4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContentProvider.kt @@ -22,6 +22,7 @@ open class TimelineItemLocationContentProvider : PreviewParameterProvider, ) : EventContent { - val endsAt = timestamp + timeout + val endTimestamp = startTimestamp + timeout } data object LegacyCallInviteContent : EventContent 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 0c41824dde..0a754a1f3c 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 @@ -44,6 +44,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.timedByExpiry import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher import io.element.android.libraries.matrix.impl.roomdirectory.map import io.element.android.libraries.matrix.impl.timeline.RustTimeline @@ -503,7 +504,7 @@ class JoinedRustRoom( } override fun subscribeToLiveLocationShares(): Flow> { - return innerRoom.liveLocationSharesFlow() + return innerRoom.liveLocationSharesFlow().timedByExpiry(systemClock::epochMillis) } override suspend fun startLiveLocationShare(durationMillis: Long): Result = withContext(roomDispatcher) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt new file mode 100644 index 0000000000..5a570d04d5 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt @@ -0,0 +1,56 @@ +/* + * 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.LiveLocationShare +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.channelFlow +import kotlinx.coroutines.launch + +/** + * Makes sure to filter and emit live location based on the endTimestamp. + */ +internal fun Flow>.timedByExpiry( + currentTimeMillis: () -> Long = System::currentTimeMillis, +): Flow> = channelFlow { + var timerJob: Job? = null + + fun List.nextExpiryAfter(timestamp: Long): Long? { + return this + .asSequence() + .map { it.endTimestamp } + .filter { it > timestamp } + .minOrNull() + } + + fun List.filterLive(): List { + val currentTimeMillis = currentTimeMillis() + return filter { it.endTimestamp > currentTimeMillis } + } + + fun reschedule(shares: List) { + timerJob?.cancel() + timerJob = launch { + val currentTimeMillis = currentTimeMillis() + val nextExpiry = shares.nextExpiryAfter(currentTimeMillis) ?: return@launch + delay((nextExpiry - currentTimeMillis).coerceAtLeast(0)) + val liveShares = shares.filterLive() + send(liveShares) + reschedule(liveShares) + } + } + + collect { shares -> + val liveShares = shares.filterLive() + send(liveShares) + reschedule(liveShares) + } + +} 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 0d940a0a11..85b53bc6e3 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 @@ -114,7 +114,7 @@ class TimelineEventContentMapper( is MsgLikeKind.LiveLocation -> { LiveLocationContent( isLive = kind.content.isLive, - timestamp = kind.content.ts.toLong(), + startTimestamp = kind.content.ts.toLong(), description = kind.content.description, timeout = kind.content.timeoutMs.toLong(), assetType = kind.content.assetType.into(), 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 new file mode 100644 index 0000000000..886b927b9a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt @@ -0,0 +1,148 @@ +/* + * 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 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 kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.runTest +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +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), + ) + + flowOf(shares) + .timedByExpiry(currentTimeMillis = { testScheduler.currentTime }) + .test { + assertThat(awaitItem()).isEqualTo(shares) + + advanceTimeBy(1_000) + assertThat(awaitItem()).isEqualTo(shares.drop(1)) + + advanceTimeBy(999) + expectNoEvents() + + advanceTimeBy(1) + assertThat(awaitItem()).isEqualTo(shares.drop(2)) + + advanceTimeBy(999) + expectNoEvents() + + advanceTimeBy(1) + assertThat(awaitItem()).isEmpty() + + awaitComplete() + } + } + + @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), + ) + + flowOf(shares) + .timedByExpiry(currentTimeMillis = { 1_000 + testScheduler.currentTime }) + .test { + assertThat(awaitItem()).isEqualTo(shares.drop(1)) + expectNoEvents() + + advanceTimeBy(999) + expectNoEvents() + + advanceTimeBy(1) + assertThat(awaitItem()).isEmpty() + + awaitComplete() + } + } + + @Test + fun `it reschedules timed emission when upstream shares change`() = runTest { + 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), + ) + + upstream + .timedByExpiry(currentTimeMillis = { testScheduler.currentTime }) + .test { + upstream.emit(initialShares) + assertThat(awaitItem()).isEqualTo(initialShares) + + advanceTimeBy(5_000) + upstream.emit(updatedShares) + assertThat(awaitItem()).isEqualTo(updatedShares) + + advanceTimeBy(999) + expectNoEvents() + + advanceTimeBy(1) + assertThat(awaitItem()).isEqualTo(updatedShares.take(1)) + + advanceTimeBy(3_999) + expectNoEvents() + + advanceTimeBy(1) + assertThat(awaitItem()).isEmpty() + } + } + + @Test + fun `it completes after the last scheduled re-emission when upstream completes`() = runTest { + val shares = listOf(aLiveLocationShare(endTimestamp = 1_000)) + flowOf(shares) + .timedByExpiry(currentTimeMillis = { testScheduler.currentTime }) + .test { + assertThat(awaitItem()).isEqualTo(shares) + + advanceTimeBy(1_000) + assertThat(awaitItem()).isEmpty() + + awaitComplete() + } + } + + @Test + fun `it completes immediately when upstream emits nothing`() = runTest { + emptyFlow>() + .timedByExpiry(currentTimeMillis = { testScheduler.currentTime }) + .test { + awaitComplete() + } + } +} + +private fun aLiveLocationShare( + userId: String = "@user:server", + endTimestamp: Long, +): LiveLocationShare { + return LiveLocationShare( + userId = UserId(userId), + lastLocation = null, + endTimestamp = endTimestamp, + ) +} 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 6502882d7d..5de2cf76da 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 @@ -12,6 +12,7 @@ import androidx.activity.ComponentActivity import androidx.annotation.StringRes import androidx.compose.ui.test.SemanticsMatcher import androidx.compose.ui.test.SemanticsNodeInteractionsProvider +import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasAnyAncestor import androidx.compose.ui.test.hasClickAction import androidx.compose.ui.test.hasContentDescription @@ -60,3 +61,10 @@ fun AndroidComposeTestRule.assertNoNodeWith val text = activity.getString(res) onNodeWithText(text).assertDoesNotExist() } + +fun AndroidComposeTestRule.assertNodeWithTextIsDisplayed(@StringRes res: Int) { + val text = activity.getString(res) + onNodeWithText(text).assertIsDisplayed() +} + + From 6b933b6506d8f931e6034c8add3ff933a7a23e3d Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 16 Apr 2026 15:52:11 +0200 Subject: [PATCH 27/44] Use "Shared live location" in formatter --- .../features/messages/impl/actionlist/ActionListView.kt | 6 +++++- .../utils/messagesummary/DefaultMessageSummaryFormatter.kt | 5 ++++- .../eventformatter/impl/DefaultRoomLatestEventFormatter.kt | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 53f15066b6..9f3b2afd2a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -289,7 +289,11 @@ private fun MessageSummary( is TimelineItemRedactedContent, is TimelineItemUnknownContent -> content = { ContentForBody(textContent) } is TimelineItemLocationContent -> { - content = { ContentForBody(stringResource(CommonStrings.common_shared_location)) } + val body = when(event.content.mode) { + is TimelineItemLocationContent.Mode.Live -> stringResource(CommonStrings.common_shared_live_location) + is TimelineItemLocationContent.Mode.Static -> stringResource(CommonStrings.common_shared_location) + } + content = { ContentForBody(body) } } is TimelineItemImageContent -> { content = { ContentForBody(event.content.bestDescription) } 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 0aeb3bb8fc..a92dedae0f 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 @@ -41,7 +41,10 @@ class DefaultMessageSummaryFormatter( is TimelineItemTextBasedContent -> content.plainText is TimelineItemProfileChangeContent -> content.body is TimelineItemStateContent -> content.body - is TimelineItemLocationContent -> context.getString(CommonStrings.common_shared_location) + is TimelineItemLocationContent -> when(content.mode) { + is TimelineItemLocationContent.Mode.Live -> context.getString(CommonStrings.common_shared_live_location) + is TimelineItemLocationContent.Mode.Static -> context.getString(CommonStrings.common_shared_location) + } is TimelineItemEncryptedContent -> context.getString(CommonStrings.common_unable_to_decrypt) is TimelineItemRedactedContent -> context.getString(CommonStrings.common_message_removed) is TimelineItemPollContent -> content.question 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 68dd4cd332..3ecd7819e5 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 @@ -117,7 +117,7 @@ class DefaultRoomLatestEventFormatter( message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is LiveLocationContent -> { - val message = sp.getString(CommonStrings.common_shared_location) + val message = sp.getString(CommonStrings.common_shared_live_location) message.prefixIfNeeded(senderDisambiguatedDisplayName, isDmRoom, isOutgoing) } is LegacyCallInviteContent -> sp.getString(CommonStrings.common_unsupported_call) From fbfeeae08476d45fa2af289dd7eb151974d424cc Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 16 Apr 2026 16:18:53 +0200 Subject: [PATCH 28/44] Fix formatting --- .../api/internal/StaticMapPlaceholder.kt | 1 - .../impl/common/ui/LocationShareRow.kt | 2 +- .../impl/show/ShowLocationPresenter.kt | 4 +- .../impl/show/ShowLocationPresenterTest.kt | 4 +- .../messages/impl/MessagesFlowNode.kt | 2 +- .../impl/actionlist/ActionListView.kt | 2 +- .../event/TimelineItemLocationView.kt | 2 - .../event/TimelineItemLocationContent.kt | 3 +- .../DefaultMessageSummaryFormatter.kt | 2 +- .../TimelineItemContentMessageFactoryTest.kt | 53 ++++++++----------- .../room/location/LiveLocationSharesFlow.kt | 1 - .../location/TimedLiveLocationSharesFlow.kt | 1 - .../TimedLiveLocationSharesFlowTest.kt | 4 +- ...nticsNodeInteractionsProviderExtensions.kt | 2 - 14 files changed, 31 insertions(+), 52 deletions(-) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt index 735a25fef9..0292ec927e 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/internal/StaticMapPlaceholder.kt @@ -28,7 +28,6 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.location.api.R import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator 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 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 d2c7ba5966..83db9a9c61 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 @@ -93,7 +93,7 @@ fun LocationShareRow( Text( text = if (item.isLive) stringResource(CommonStrings.screen_room_live_location_banner) else item.formattedTimestamp, style = ElementTheme.typography.fontBodySmRegular, - color = if(item.isLive) ElementTheme.colors.textPrimary else ElementTheme.colors.textSecondary, + color = if (item.isLive) ElementTheme.colors.textPrimary else ElementTheme.colors.textSecondary, maxLines = 1, overflow = TextOverflow.Ellipsis, ) 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 10501409fe..6b05e473c6 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 @@ -43,7 +43,7 @@ import io.element.android.libraries.matrix.api.room.joinedRoomMembers import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toPersistentList +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.combine @AssistedInject @@ -161,7 +161,7 @@ class ShowLocationPresenter( isLive = true, assetType = lastLocation.assetType, ) - }.toPersistentList() + }.toImmutableList() }.collect { value = it } }.value } 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 c5120928dc..5369c441f8 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 @@ -434,7 +434,7 @@ class ShowLocationPresenterTest { senderName = senderName, senderId = senderId, senderAvatarUrl = avatarUrl, - timestamp = 1234567890L, + timestamp = 0L, assetType = AssetType.SENDER, ) @@ -468,7 +468,7 @@ class ShowLocationPresenterTest { private fun aLiveLocationShare( userId: UserId, geoUri: String = "geo:48.8584,2.2945", - timestamp: Long = 1234567890L, + timestamp: Long = 0L, endTimestamp: Long = Long.MAX_VALUE, assetType: AssetType = AssetType.SENDER, ): LiveLocationShare { 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 5affdb4484..690f895e07 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 @@ -570,7 +570,7 @@ class MessagesFlowNode( ) } is TimelineItemLocationContent -> { - val mode = when(event.content.mode){ + val mode = when (event.content.mode) { is TimelineItemLocationContent.Mode.Live -> ShowLocationMode.Live(event.senderId) is TimelineItemLocationContent.Mode.Static -> ShowLocationMode.Static( location = event.content.mode.location, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 9f3b2afd2a..ef446e36cf 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -289,7 +289,7 @@ private fun MessageSummary( is TimelineItemRedactedContent, is TimelineItemUnknownContent -> content = { ContentForBody(textContent) } is TimelineItemLocationContent -> { - val body = when(event.content.mode) { + val body = when (event.content.mode) { is TimelineItemLocationContent.Mode.Live -> stringResource(CommonStrings.common_shared_live_location) is TimelineItemLocationContent.Mode.Static -> stringResource(CommonStrings.common_shared_location) } 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 1c35216c38..f00b6b0b5b 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 @@ -33,7 +33,6 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.location.api.StaticMapView import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemLocationContentProvider -import io.element.android.features.messages.impl.timeline.model.event.ensureActiveLiveLocation import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator @@ -129,7 +128,6 @@ private fun LiveLocationOverlay( } else { stringResource(CommonStrings.common_live_location_ended) }, - style = ElementTheme.typography.fontBodySmMedium, color = ElementTheme.colors.textPrimary, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt index 8fb4d50427..40af75c82c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemLocationContent.kt @@ -88,7 +88,7 @@ data class TimelineItemLocationContent( internal fun TimelineItemLocationContent.ensureActiveLiveLocation( currentTimeMillis: () -> Long = System::currentTimeMillis, ): TimelineItemLocationContent { - return when (val mode = mode) { + return when (mode) { is TimelineItemLocationContent.Mode.Live -> { val isActive = rememberIsLiveLocationActive(mode, currentTimeMillis) copy(mode = mode.copy(isActive = isActive)) @@ -102,7 +102,6 @@ private fun rememberIsLiveLocationActive( mode: TimelineItemLocationContent.Mode.Live, currentTimeMillis: () -> Long, ): Boolean { - fun TimelineItemLocationContent.Mode.Live.isActive(): Boolean { return isActive && endTimestamp > currentTimeMillis() } 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 a92dedae0f..c48f2dae40 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 @@ -41,7 +41,7 @@ class DefaultMessageSummaryFormatter( is TimelineItemTextBasedContent -> content.plainText is TimelineItemProfileChangeContent -> content.body is TimelineItemStateContent -> content.body - is TimelineItemLocationContent -> when(content.mode) { + is TimelineItemLocationContent -> when (content.mode) { is TimelineItemLocationContent.Mode.Live -> context.getString(CommonStrings.common_shared_live_location) is TimelineItemLocationContent.Mode.Static -> context.getString(CommonStrings.common_shared_location) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt index e6ef18d00d..fa837f1492 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/factories/event/TimelineItemContentMessageFactoryTest.kt @@ -78,9 +78,7 @@ import org.robolectric.RobolectricTestRunner import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes -@Suppress("LargeClass") -@RunWith(RobolectricTestRunner::class) -class TimelineItemContentMessageFactoryTest { +@Suppress("LargeClass") @RunWith(RobolectricTestRunner::class) class TimelineItemContentMessageFactoryTest { @Test fun `test create OtherMessageType`() = runTest { val sut = createTimelineItemContentMessageFactory() @@ -164,16 +162,11 @@ class TimelineItemContentMessageFactoryTest { senderProfile = aProfileDetails(), eventId = AN_EVENT_ID, ) as TimelineItemTextContent - val expected = TimelineItemTextContent( - body = "https://www.example.org", - htmlDocument = null, - isEdited = false, - formattedBody = buildSpannedString { - inSpans(URLSpan("https://www.example.org")) { - append("https://www.example.org") - } + val expected = TimelineItemTextContent(body = "https://www.example.org", htmlDocument = null, isEdited = false, formattedBody = buildSpannedString { + inSpans(URLSpan("https://www.example.org")) { + append("https://www.example.org") } - ) + }) assertThat(result.body).isEqualTo(expected.body) assertThat(result.htmlDocument).isEqualTo(expected.htmlDocument) assertThat(result.plainText).isEqualTo(expected.plainText) @@ -198,9 +191,7 @@ class TimelineItemContentMessageFactoryTest { append("and manually added link") } }.toSpannable() - val sut = createTimelineItemContentMessageFactory( - domConverterTransform = { expected } - ) + val sut = createTimelineItemContentMessageFactory(domConverterTransform = { expected }) val result = sut.create( content = createMessageContent( type = TextMessageType( @@ -217,9 +208,7 @@ class TimelineItemContentMessageFactoryTest { @Test fun `test create TextMessageType with unknown formatted body does nothing`() = runTest { - val sut = createTimelineItemContentMessageFactory( - htmlConverterTransform = { it } - ) + val sut = createTimelineItemContentMessageFactory(htmlConverterTransform = { it }) val result = sut.create( content = createMessageContent( type = TextMessageType( @@ -354,10 +343,10 @@ class TimelineItemContentMessageFactoryTest { formattedCaption = null, source = MediaSource("url"), info = AudioInfo( - duration = 1.minutes, - size = 123L, - mimetype = MimeTypes.Mp3, - ) + duration = 1.minutes, + size = 123L, + mimetype = MimeTypes.Mp3, + ) ), isEdited = true, ), @@ -595,16 +584,16 @@ class TimelineItemContentMessageFactoryTest { formattedCaption = null, source = MediaSource("url"), info = FileInfo( - mimetype = MimeTypes.Pdf, - size = 123L, - thumbnailInfo = ThumbnailInfo( - height = 10L, - width = 5L, - mimetype = MimeTypes.Jpeg, - size = 111L, - ), - thumbnailSource = MediaSource("url_thumbnail"), - ) + mimetype = MimeTypes.Pdf, + size = 123L, + thumbnailInfo = ThumbnailInfo( + height = 10L, + width = 5L, + mimetype = MimeTypes.Jpeg, + size = 111L, + ), + thumbnailSource = MediaSource("url_thumbnail"), + ) ), isEdited = true, ), 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 4f4ddac667..8922cd6627 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 @@ -71,4 +71,3 @@ private fun RustLiveLocationShare.into(): LiveLocationShare { endTimestamp = (startTs + timeout).toLong() ) } - diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt index 5a570d04d5..9bfddf280f 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/location/TimedLiveLocationSharesFlow.kt @@ -52,5 +52,4 @@ internal fun Flow>.timedByExpiry( send(liveShares) reschedule(liveShares) } - } 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 886b927b9a..6c78fcc51b 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 @@ -12,9 +12,8 @@ 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 kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest @@ -22,7 +21,6 @@ import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class TimedLiveLocationSharesFlowTest { - @Test fun `it keeps emitting shares for subsequent expiries without upstream changes`() = runTest { val shares = listOf( 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 5de2cf76da..d78f570a31 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 @@ -66,5 +66,3 @@ fun AndroidComposeTestRule.assertNodeWithTe val text = activity.getString(res) onNodeWithText(text).assertIsDisplayed() } - - From 555d7acbd3b13504fbb002ec1dd569df077186dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 00:03:24 +0000 Subject: [PATCH 29/44] Update actions/github-script action to v9 --- .github/workflows/fork-pr-notice.yml | 2 +- .github/workflows/post-release.yml | 2 +- .github/workflows/pull_request.yml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/fork-pr-notice.yml b/.github/workflows/fork-pr-notice.yml index af3e4a3006..3e67d97eac 100644 --- a/.github/workflows/fork-pr-notice.yml +++ b/.github/workflows/fork-pr-notice.yml @@ -20,7 +20,7 @@ jobs: if: github.event.pull_request.base.repo.full_name != github.event.pull_request.head.repo.full_name steps: - name: Add auto-generated commit warning - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | github.rest.issues.createComment({ diff --git a/.github/workflows/post-release.yml b/.github/workflows/post-release.yml index 5349a678bc..6efeff17be 100644 --- a/.github/workflows/post-release.yml +++ b/.github/workflows/post-release.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Trigger pipeline - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: github-token: ${{ secrets.ENTERPRISE_ACTIONS_TOKEN }} script: | diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d90cf07e50..c8c0a98dea 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -17,7 +17,7 @@ jobs: pull-requests: read steps: - name: Add notice - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 if: contains(github.event.pull_request.labels.*.name, 'X-Blocked') with: script: | @@ -41,7 +41,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN_READ_ORG }} - name: Add label if: steps.teams.outputs.isTeamMember == 'false' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | github.rest.issues.addLabels({ @@ -63,7 +63,7 @@ jobs: github.event.pull_request.head.repo.full_name != github.repository steps: - name: Close pull request - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | github.rest.issues.createComment({ From a1c9994385797a71c0007e33b6adc6ac92ac91a4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Apr 2026 12:39:08 +0200 Subject: [PATCH 30/44] Settings UI update. - Reorder items - Minor UI update - Improve the previews of the Composable - Merge manage account and manage devices - Add missing tests --- .../appnav/loggedin/LoggedInPresenter.kt | 4 +- .../appnav/loggedin/LoggedInPresenterTest.kt | 9 +- ...sRootEvents.kt => PreferencesRootEvent.kt} | 6 +- .../impl/root/PreferencesRootPresenter.kt | 23 +- .../impl/root/PreferencesRootState.kt | 9 +- .../impl/root/PreferencesRootStateProvider.kt | 101 +++- .../impl/root/PreferencesRootView.kt | 133 ++--- .../preferences/impl/user/UserPreferences.kt | 8 +- .../impl/root/PreferencesRootPresenterTest.kt | 61 ++- .../impl/root/PreferencesRootViewTest.kt | 483 ++++++++++++++++++ .../components/avatar/AvatarSize.kt | 2 +- .../preview/ElementPreviewDark.kt | 9 +- .../preview/ElementPreviewLight.kt | 9 +- .../matrix/ui/components/MatrixUserHeader.kt | 36 +- .../components/MatrixUserHeaderPlaceholder.kt | 64 --- .../ui/components/MatrixUserProvider.kt | 9 - .../matrix/ui/components/MatrixUserRow.kt | 4 + .../libraries/matrix/ui/components/UserRow.kt | 11 +- 18 files changed, 733 insertions(+), 248 deletions(-) rename features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/{PreferencesRootEvents.kt => PreferencesRootEvent.kt} (78%) create mode 100644 features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt delete mode 100644 libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt diff --git a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt index 8dc2de5e4e..752d10e7a9 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt @@ -31,7 +31,6 @@ import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.RecoveryState -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.roomlist.RoomListService import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion import io.element.android.libraries.matrix.api.sync.SyncService @@ -177,7 +176,6 @@ class LoggedInPresenter( } private fun CoroutineScope.preloadAccountManagementUrl() = launch { - matrixClient.getAccountManagementUrl(AccountManagementAction.Profile) - matrixClient.getAccountManagementUrl(AccountManagementAction.DevicesList) + matrixClient.getAccountManagementUrl(null) } } diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt index d147a4ed68..902f446a6f 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt @@ -71,7 +71,7 @@ class LoggedInPresenterTest { } @Test - fun `present - ensure that account urls are preloaded`() = runTest { + fun `present - ensure that account url is preloaded`() = runTest { val accountManagementUrlResult = lambdaRecorder> { Result.success("aUrl") } val matrixClient = FakeMatrixClient( accountManagementUrlResult = accountManagementUrlResult, @@ -81,11 +81,8 @@ class LoggedInPresenterTest { ).test { awaitItem() advanceUntilIdle() - accountManagementUrlResult.assertions().isCalledExactly(2) - .withSequence( - listOf(value(AccountManagementAction.Profile)), - listOf(value(AccountManagementAction.DevicesList)), - ) + accountManagementUrlResult.assertions().isCalledOnce() + .with(value(null)) } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvents.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt similarity index 78% rename from features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvents.kt rename to features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt index be266869be..5a10a50ba6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvents.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootEvent.kt @@ -10,7 +10,7 @@ package io.element.android.features.preferences.impl.root import io.element.android.libraries.matrix.api.core.SessionId -sealed interface PreferencesRootEvents { - data object OnVersionInfoClick : PreferencesRootEvents - data class SwitchToSession(val sessionId: SessionId) : PreferencesRootEvents +sealed interface PreferencesRootEvent { + data object OnVersionInfoClick : PreferencesRootEvent + data class SwitchToSession(val sessionId: SessionId) : PreferencesRootEvent } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt index 3d6a829167..43da681a37 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt @@ -30,7 +30,6 @@ import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.indicator.api.IndicatorService import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.UserId -import io.element.android.libraries.matrix.api.oidc.AccountManagementAction import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.sessionstorage.api.SessionStore @@ -99,9 +98,6 @@ class PreferencesRootPresenter( val accountManagementUrl: MutableState = remember { mutableStateOf(null) } - val devicesManagementUrl: MutableState = remember { - mutableStateOf(null) - } var canDeactivateAccount by remember { mutableStateOf(false) } @@ -110,9 +106,9 @@ class PreferencesRootPresenter( canDeactivateAccount = matrixClient.canDeactivateAccount() } - val showBlockedUsersItem by produceState(initialValue = false) { + val nbOfBlockedUsers by produceState(initialValue = 0) { matrixClient.ignoredUsersFlow - .onEach { value = it.isNotEmpty() } + .onEach { value = it.size } .launchIn(this) } @@ -121,17 +117,17 @@ class PreferencesRootPresenter( val directLogoutState = directLogoutPresenter.present() LaunchedEffect(Unit) { - initAccountManagementUrl(accountManagementUrl, devicesManagementUrl) + initAccountManagementUrl(accountManagementUrl) } val showDeveloperSettings by showDeveloperSettingsProvider.showDeveloperSettings.collectAsState() - fun handleEvent(event: PreferencesRootEvents) { + fun handleEvent(event: PreferencesRootEvent) { when (event) { - is PreferencesRootEvents.OnVersionInfoClick -> { + is PreferencesRootEvent.OnVersionInfoClick -> { showDeveloperSettingsProvider.unlockDeveloperSettings(coroutineScope) } - is PreferencesRootEvents.SwitchToSession -> coroutineScope.launch { + is PreferencesRootEvent.SwitchToSession -> coroutineScope.launch { sessionStore.setLatestSession(event.sessionId.value) } } @@ -146,13 +142,12 @@ class PreferencesRootPresenter( showSecureBackup = !canVerifyUserSession, showSecureBackupBadge = showSecureBackupIndicator, accountManagementUrl = accountManagementUrl.value, - devicesManagementUrl = devicesManagementUrl.value, showAnalyticsSettings = hasAnalyticsProviders, canReportBug = canReportBug, showLinkNewDevice = showLinkNewDevice, showDeveloperSettings = showDeveloperSettings, canDeactivateAccount = canDeactivateAccount, - showBlockedUsersItem = showBlockedUsersItem, + nbOfBlockedUsers = nbOfBlockedUsers, showLabsItem = showLabsItem, directLogoutState = directLogoutState, snackbarMessage = snackbarMessage, @@ -162,9 +157,7 @@ class PreferencesRootPresenter( private fun CoroutineScope.initAccountManagementUrl( accountManagementUrl: MutableState, - devicesManagementUrl: MutableState, ) = launch { - accountManagementUrl.value = matrixClient.getAccountManagementUrl(AccountManagementAction.Profile).getOrNull() - devicesManagementUrl.value = matrixClient.getAccountManagementUrl(AccountManagementAction.DevicesList).getOrNull() + accountManagementUrl.value = matrixClient.getAccountManagementUrl(null).getOrNull() } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt index d637ae6c87..6474f07a69 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt @@ -23,15 +23,16 @@ data class PreferencesRootState( val showSecureBackup: Boolean, val showSecureBackupBadge: Boolean, val accountManagementUrl: String?, - val devicesManagementUrl: String?, val canReportBug: Boolean, val showLinkNewDevice: Boolean, val showAnalyticsSettings: Boolean, val showDeveloperSettings: Boolean, val canDeactivateAccount: Boolean, - val showBlockedUsersItem: Boolean, + val nbOfBlockedUsers: Int, val showLabsItem: Boolean, val directLogoutState: DirectLogoutState, val snackbarMessage: SnackbarMessage?, - val eventSink: (PreferencesRootEvents) -> Unit, -) + val eventSink: (PreferencesRootEvent) -> Unit, +) { + val showBlockedUsersItem = nbOfBlockedUsers > 0 +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index b8d1f1c2b6..d53cd008e4 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -8,36 +8,103 @@ package io.element.android.features.preferences.impl.root +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.logout.api.direct.DirectLogoutState import io.element.android.features.logout.api.direct.aDirectLogoutState import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser +import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.toImmutableList +open class PreferencesRootStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + // Nominal state, that a regular user will see if multi account is enabled + aPreferencesRootState( + myUser = aMatrixUser(avatarUrl = "anAvatarUrl"), + version = "Version 1.1 (1)", + deviceId = DeviceId("ILAKNDNASDLK"), + isMultiAccountEnabled = true, + otherSessions = aMatrixUserList().drop(1).take(1), + showSecureBackup = true, + accountManagementUrl = "aUrl", + canReportBug = true, + showLinkNewDevice = true, + showAnalyticsSettings = true, + canDeactivateAccount = false, + nbOfBlockedUsers = 3, + showLabsItem = true, + ), + aPreferencesRootState( + myUser = aMatrixUser(displayName = null), + isMultiAccountEnabled = true, + showSecureBackup = true, + canDeactivateAccount = true, + ), + aPreferencesRootState( + isMultiAccountEnabled = true, + otherSessions = aMatrixUserList().drop(1).take(3), + accountManagementUrl = "aUrl", + showSecureBackup = true, + showSecureBackupBadge = true, + ), + aPreferencesRootState( + deviceId = DeviceId("ILAKNDNASDLK"), + showLabsItem = true, + canReportBug = true, + nbOfBlockedUsers = 3, + snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), + ), + aPreferencesRootState( + showLinkNewDevice = true, + showAnalyticsSettings = true, + showDeveloperSettings = true, + canDeactivateAccount = true, + ), + // Minimal state + aPreferencesRootState(), + ) +} + fun aPreferencesRootState( myUser: MatrixUser = aMatrixUser(), + version: String = "Version 1.1 (1)", + deviceId: DeviceId? = null, + isMultiAccountEnabled: Boolean = false, otherSessions: List = emptyList(), - eventSink: (PreferencesRootEvents) -> Unit = { _ -> }, + showSecureBackup: Boolean = false, + showSecureBackupBadge: Boolean = false, + accountManagementUrl: String? = null, + canReportBug: Boolean = false, + showLinkNewDevice: Boolean = false, + showAnalyticsSettings: Boolean = false, + showDeveloperSettings: Boolean = false, + canDeactivateAccount: Boolean = false, + nbOfBlockedUsers: Int = 0, + showLabsItem: Boolean = false, + directLogoutState: DirectLogoutState = aDirectLogoutState(), + snackbarMessage: SnackbarMessage? = null, + eventSink: (PreferencesRootEvent) -> Unit = {}, ) = PreferencesRootState( myUser = myUser, - version = "Version 1.1 (1)", - deviceId = DeviceId("ILAKNDNASDLK"), - isMultiAccountEnabled = true, + version = version, + deviceId = deviceId, + isMultiAccountEnabled = isMultiAccountEnabled, otherSessions = otherSessions.toImmutableList(), - showSecureBackup = true, - showSecureBackupBadge = true, - accountManagementUrl = "aUrl", - devicesManagementUrl = "anOtherUrl", - showAnalyticsSettings = true, - showLinkNewDevice = true, - canReportBug = true, - showDeveloperSettings = true, - showBlockedUsersItem = true, - showLabsItem = true, - canDeactivateAccount = true, - snackbarMessage = SnackbarMessage(CommonStrings.common_verification_complete), - directLogoutState = aDirectLogoutState(), + showSecureBackup = showSecureBackup, + showSecureBackupBadge = showSecureBackupBadge, + accountManagementUrl = accountManagementUrl, + canReportBug = canReportBug, + showLinkNewDevice = showLinkNewDevice, + showAnalyticsSettings = showAnalyticsSettings, + showDeveloperSettings = showDeveloperSettings, + canDeactivateAccount = canDeactivateAccount, + nbOfBlockedUsers = nbOfBlockedUsers, + showLabsItem = showLabsItem, + directLogoutState = directLogoutState, + snackbarMessage = snackbarMessage, eventSink = eventSink, ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index 5e3c9d6759..32ecfc2b13 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -9,7 +9,6 @@ package io.element.android.features.preferences.impl.root import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable @@ -28,23 +27,20 @@ import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.list.ListItemContent import io.element.android.libraries.designsystem.components.preferences.PreferencePage -import io.element.android.libraries.designsystem.preview.ElementPreview 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.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.ListItem import io.element.android.libraries.designsystem.theme.components.ListItemStyle import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.ui.components.MatrixUserProvider import io.element.android.libraries.matrix.ui.components.MatrixUserRow -import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.ui.strings.CommonStrings @Composable @@ -82,22 +78,17 @@ fun PreferencesRootView( modifier = Modifier.clickable { onOpenUserProfile(state.myUser) }, - user = state.myUser, + matrixUser = state.myUser, ) if (state.isMultiAccountEnabled) { MultiAccountSection( state = state, onAddAccountClick = onAddAccountClick, ) + } else { + HorizontalDivider() } - // 'Manage my app' section - ManageAppSection( - state = state, - onOpenNotificationSettings = onOpenNotificationSettings, - onOpenLockScreenSettings = onOpenLockScreenSettings, - onSecureBackupClick = onSecureBackupClick, - ) - + // User status will be added here // 'Account' section ManageAccountSection( state = state, @@ -105,6 +96,13 @@ fun PreferencesRootView( onLinkNewDeviceClick = onLinkNewDeviceClick, onOpenBlockedUsers = onOpenBlockedUsers ) + // 'Manage my app' section + ManageAppSection( + state = state, + onOpenNotificationSettings = onOpenNotificationSettings, + onOpenLockScreenSettings = onOpenLockScreenSettings, + onSecureBackupClick = onSecureBackupClick, + ) // General section GeneralSection( @@ -118,12 +116,12 @@ fun PreferencesRootView( onSignOutClick = onSignOutClick, onDeactivateClick = onDeactivateClick, ) - + // Version Footer( version = state.version, deviceId = state.deviceId, onClick = if (!state.showDeveloperSettings) { - { state.eventSink(PreferencesRootEvents.OnVersionInfoClick) } + { state.eventSink(PreferencesRootEvent.OnVersionInfoClick) } } else { null } @@ -142,13 +140,15 @@ private fun ColumnScope.MultiAccountSection( ) state.otherSessions.forEach { matrixUser -> MatrixUserRow( - modifier = Modifier.clickable { - state.eventSink(PreferencesRootEvents.SwitchToSession(matrixUser.userId)) - }, + modifier = Modifier + .clickable { + state.eventSink(PreferencesRootEvent.SwitchToSession(matrixUser.userId)) + } + .padding(top = 2.dp, bottom = 2.dp, end = 8.dp), matrixUser = matrixUser, avatarSize = AvatarSize.AccountItem, + verticalSpaceWidth = 16.dp, ) - HorizontalDivider() } ListItem( leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Plus())), @@ -198,6 +198,14 @@ private fun ColumnScope.ManageAccountSection( onLinkNewDeviceClick: () -> Unit, onOpenBlockedUsers: () -> Unit, ) { + state.accountManagementUrl?.let { url -> + ListItem( + headlineContent = { Text(stringResource(id = CommonStrings.action_manage_account_and_devices)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), + trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())), + onClick = { onManageAccountClick(url) }, + ) + } if (state.showLinkNewDevice) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_link_new_device)) }, @@ -205,33 +213,15 @@ private fun ColumnScope.ManageAccountSection( onClick = onLinkNewDeviceClick, ) } - state.accountManagementUrl?.let { url -> - ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_manage_account)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.UserProfile())), - trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())), - onClick = { onManageAccountClick(url) }, - ) - } - - state.devicesManagementUrl?.let { url -> - ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.action_manage_devices)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Devices())), - trailingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.PopOut())), - onClick = { onManageAccountClick(url) }, - ) - } - if (state.showBlockedUsersItem) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_blocked_users)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Block())), onClick = onOpenBlockedUsers, + trailingContent = ListItemContent.Text(state.nbOfBlockedUsers.toString()), ) } - - if (state.accountManagementUrl != null || state.devicesManagementUrl != null || state.showBlockedUsersItem) { + if (state.accountManagementUrl != null || state.showLinkNewDevice || state.showBlockedUsersItem) { HorizontalDivider() } } @@ -248,6 +238,18 @@ private fun ColumnScope.GeneralSection( onSignOutClick: () -> Unit, onDeactivateClick: () -> Unit, ) { + ListItem( + headlineContent = { Text(stringResource(id = CommonStrings.common_advanced_settings)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Settings())), + onClick = onOpenAdvancedSettings, + ) + if (state.showLabsItem) { + ListItem( + headlineContent = { Text(stringResource(id = R.string.screen_labs_title)) }, + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Labs())), + onClick = onOpenLabs, + ) + } ListItem( headlineContent = { Text(stringResource(id = CommonStrings.common_about)) }, leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Info())), @@ -267,30 +269,17 @@ private fun ColumnScope.GeneralSection( onClick = onOpenAnalytics, ) } - ListItem( - headlineContent = { Text(stringResource(id = CommonStrings.common_advanced_settings)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Settings())), - onClick = onOpenAdvancedSettings, - ) - - if (state.showLabsItem) { - ListItem( - headlineContent = { Text(stringResource(id = R.string.screen_labs_title)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Labs())), - onClick = onOpenLabs, - ) - } - + HorizontalDivider() ListItem( headlineContent = { Text(stringResource(id = CommonStrings.action_signout)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.SignOut())), + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Close())), style = ListItemStyle.Destructive, onClick = onSignOutClick, ) if (state.canDeactivateAccount) { ListItem( headlineContent = { Text(stringResource(id = CommonStrings.action_deactivate_account)) }, - leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Warning())), + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Delete())), style = ListItemStyle.Destructive, onClick = onDeactivateClick, ) @@ -319,9 +308,8 @@ private fun ColumnScope.Footer( Text( modifier = Modifier .align(Alignment.CenterHorizontally) - .padding(top = 16.dp) .clickable(enabled = onClick != null, onClick = onClick ?: {}) - .padding(start = 16.dp, end = 16.dp, top = 24.dp, bottom = 24.dp), + .padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 24.dp), textAlign = TextAlign.Center, text = text, style = ElementTheme.typography.fontBodySmRegular, @@ -340,19 +328,23 @@ private fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) { @PreviewWithLargeHeight @Composable -internal fun PreferencesRootViewLightPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = - ElementPreviewLight { ContentToPreview(matrixUser) } +internal fun PreferencesRootViewLightPreview(@PreviewParameter(PreferencesRootStateProvider::class) state: PreferencesRootState) = + ElementPreviewLight( + drawableFallbackForImages = CommonDrawables.sample_avatar, + ) { ContentToPreview(state) } @PreviewWithLargeHeight @Composable -internal fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = - ElementPreviewDark { ContentToPreview(matrixUser) } +internal fun PreferencesRootViewDarkPreview(@PreviewParameter(PreferencesRootStateProvider::class) state: PreferencesRootState) = + ElementPreviewDark( + drawableFallbackForImages = CommonDrawables.sample_avatar, + ) { ContentToPreview(state) } @ExcludeFromCoverage @Composable -private fun ContentToPreview(matrixUser: MatrixUser) { +private fun ContentToPreview(state: PreferencesRootState) { PreferencesRootView( - state = aPreferencesRootState(myUser = matrixUser), + state = state, onBackClick = {}, onAddAccountClick = {}, onOpenAnalytics = {}, @@ -372,16 +364,3 @@ private fun ContentToPreview(matrixUser: MatrixUser) { onDeactivateClick = {}, ) } - -@PreviewsDayNight -@Composable -internal fun MultiAccountSectionPreview() = ElementPreview { - Column { - MultiAccountSection( - state = aPreferencesRootState( - otherSessions = aMatrixUserList(), - ), - onAddAccountClick = {}, - ) - } -} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt index a9066dcd73..43c7e8dacf 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt @@ -15,21 +15,21 @@ import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.MatrixUserHeader -import io.element.android.libraries.matrix.ui.components.MatrixUserWithNullProvider +import io.element.android.libraries.matrix.ui.components.MatrixUserProvider @Composable fun UserPreferences( - user: MatrixUser?, + matrixUser: MatrixUser, modifier: Modifier = Modifier, ) { MatrixUserHeader( modifier = modifier, - matrixUser = user + matrixUser = matrixUser, ) } @PreviewsDayNight @Composable -internal fun UserPreferencesPreview(@PreviewParameter(MatrixUserWithNullProvider::class) matrixUser: MatrixUser?) = ElementPreview { +internal fun UserPreferencesPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview { UserPreferences(matrixUser) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt index f0dc58ef22..e5d48ec175 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt @@ -28,6 +28,8 @@ import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.test.AN_AVATAR_URL 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.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.core.aBuildMeta @@ -40,7 +42,9 @@ import io.element.android.tests.testutils.WarmUpRule 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.collections.immutable.persistentListOf import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -73,6 +77,7 @@ class PreferencesRootPresenterTest { assertThat(initialState.version).isEqualTo("A Version") assertThat(initialState.isMultiAccountEnabled).isFalse() assertThat(initialState.otherSessions).isEmpty() + assertThat(initialState.version).isEqualTo("A Version") val loadedState = awaitItem() assertThat(loadedState.myUser).isEqualTo( MatrixUser( @@ -81,27 +86,21 @@ class PreferencesRootPresenterTest { avatarUrl = AN_AVATAR_URL ) ) - assertThat(initialState.version).isEqualTo("A Version") assertThat(loadedState.showSecureBackup).isFalse() assertThat(loadedState.showSecureBackupBadge).isFalse() assertThat(loadedState.accountManagementUrl).isNull() - assertThat(loadedState.devicesManagementUrl).isNull() assertThat(loadedState.showAnalyticsSettings).isFalse() assertThat(loadedState.showLinkNewDevice).isFalse() assertThat(loadedState.showDeveloperSettings).isTrue() assertThat(loadedState.canDeactivateAccount).isTrue() assertThat(loadedState.canReportBug).isTrue() + assertThat(loadedState.nbOfBlockedUsers).isEqualTo(0) assertThat(loadedState.directLogoutState).isEqualTo(aDirectLogoutState()) assertThat(loadedState.snackbarMessage).isNull() - skipItems(1) val finalState = awaitItem() - accountManagementUrlResult.assertions().isCalledExactly(2) - .withSequence( - listOf(value(AccountManagementAction.Profile)), - listOf(value(AccountManagementAction.DevicesList)), - ) - assertThat(finalState.accountManagementUrl).isEqualTo("Profile url") - assertThat(finalState.devicesManagementUrl).isEqualTo("DevicesList url") + accountManagementUrlResult.assertions().isCalledOnce() + .with(value(null)) + assertThat(finalState.accountManagementUrl).isEqualTo("null url") } } @@ -121,6 +120,22 @@ class PreferencesRootPresenterTest { } } + @Test + fun `present - number of blocked users`() = runTest { + val matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { true }, + accountManagementUrlResult = { Result.success("") }, + ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID, A_USER_ID_2)), + ) + createPresenter( + matrixClient = matrixClient, + ).test { + skipItems(1) + val initialState = awaitItem() + assertThat(initialState.nbOfBlockedUsers).isEqualTo(2) + } + } + @Test fun `present - secure backup badge`() = runTest { val matrixClient = FakeMatrixClient( @@ -181,12 +196,36 @@ class PreferencesRootPresenterTest { val loadedState = awaitFirstItem() repeat(times = ShowDeveloperSettingsProvider.DEVELOPER_SETTINGS_COUNTER) { assertThat(loadedState.showDeveloperSettings).isFalse() - loadedState.eventSink(PreferencesRootEvents.OnVersionInfoClick) + loadedState.eventSink(PreferencesRootEvent.OnVersionInfoClick) } assertThat(awaitItem().showDeveloperSettings).isTrue() } } + @Test + fun `present - switch session invoke method on the session store`() = runTest { + val setLatestSessionResult = lambdaRecorder { } + val sessionStore = InMemorySessionStore( + initialList = listOf( + aSessionData(sessionId = A_SESSION_ID.value), + aSessionData(sessionId = A_SESSION_ID_2.value), + ), + setLatestSessionResult = setLatestSessionResult, + ) + createPresenter( + matrixClient = FakeMatrixClient( + canDeactivateAccountResult = { true }, + accountManagementUrlResult = { Result.success(null) }, + ), + sessionStore = sessionStore, + ).test { + val loadedState = awaitFirstItem() + loadedState.eventSink(PreferencesRootEvent.SwitchToSession(A_SESSION_ID_2)) + setLatestSessionResult.assertions().isCalledOnce() + .with(value(A_SESSION_ID_2.value)) + } + } + @Test fun `present - labs can be shown if any feature flag is in labs and not finished`() = runTest { createPresenter( diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt new file mode 100644 index 0000000000..e3c0d6e44d --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootViewTest.kt @@ -0,0 +1,483 @@ +/* + * 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.preferences.impl.root + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.preferences.impl.R +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.ui.components.aMatrixUser +import io.element.android.libraries.ui.strings.CommonStrings +import io.element.android.tests.testutils.EnsureNeverCalled +import io.element.android.tests.testutils.EnsureNeverCalledWithParam +import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn +import io.element.android.tests.testutils.ensureCalledOnce +import io.element.android.tests.testutils.ensureCalledOnceWithParam +import io.element.android.tests.testutils.pressBack +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TestRule +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PreferencesRootViewTest { + @get:Rule val rule = createAndroidComposeRule() + + @Test + fun `clicking on back invokes back callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder + ), + onBackClick = callback, + ) + rule.pressBack() + } + } + + @Test + fun `click on User profile invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + val user = aMatrixUser() + ensureCalledOnceWithParam(user) { callback -> + rule.setView( + aPreferencesRootState( + myUser = user, + eventSink = eventsRecorder, + ), + onOpenUserProfile = callback, + ) + rule.onNodeWithText("Alice").performClick() + } + } + + @Test + fun `clicking on other session sends a SwitchToSession`() { + val eventsRecorder = EventsRecorder() + rule.setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + otherSessions = listOf( + aMatrixUser( + id = A_USER_ID_2.value, + displayName = "Bob", + ) + ), + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText("Bob").performClick() + eventsRecorder.assertSingle(PreferencesRootEvent.SwitchToSession(A_USER_ID_2)) + } + + @Test + fun `click on Add account invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + isMultiAccountEnabled = true, + eventSink = eventsRecorder, + ), + onAddAccountClick = callback, + ) + rule.clickOn(CommonStrings.common_add_another_account) + } + } + + @Test + fun `when multi account is not enabled, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + isMultiAccountEnabled = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_add_another_account)).assertDoesNotExist() + } + + @Test + fun `click on Encryption invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showSecureBackup = true, + eventSink = eventsRecorder, + ), + onSecureBackupClick = callback, + ) + rule.clickOn(CommonStrings.common_encryption) + } + } + + @Test + fun `when showSecureBackup is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showSecureBackup = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_encryption)).assertDoesNotExist() + } + + @Test + fun `click on Manage account invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnceWithParam("aUrl") { callback -> + rule.setView( + aPreferencesRootState( + accountManagementUrl = "aUrl", + eventSink = eventsRecorder, + ), + onManageAccountClick = callback, + ) + rule.clickOn(CommonStrings.action_manage_account_and_devices) + } + } + + @Test + fun `when accountManagementUrl is null, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + accountManagementUrl = null, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.action_manage_account_and_devices)).assertDoesNotExist() + } + + @Test + fun `click on Link new devices invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showLinkNewDevice = true, + eventSink = eventsRecorder, + ), + onLinkNewDeviceClick = callback, + ) + rule.clickOn(CommonStrings.common_link_new_device) + } + } + + @Test + fun `when showLinkNewDevice is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showLinkNewDevice = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_link_new_device)).assertDoesNotExist() + } + + @Test + fun `click on Analytics invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showAnalyticsSettings = true, + eventSink = eventsRecorder, + ), + onOpenAnalytics = callback, + ) + rule.clickOn(CommonStrings.common_analytics) + } + } + + @Test + fun `when showAnalyticsSettings is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showAnalyticsSettings = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_analytics)).assertDoesNotExist() + } + + @Test + fun `click on Report a problem invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + canReportBug = true, + eventSink = eventsRecorder, + ), + onOpenRageShake = callback, + ) + rule.clickOn(CommonStrings.common_report_a_problem) + } + } + + @Test + fun `when canReportBug is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + canReportBug = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_report_a_problem)).assertDoesNotExist() + } + + @Test + fun `click on Screen lock invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenLockScreenSettings = callback, + ) + rule.clickOn(CommonStrings.common_screen_lock) + } + } + + @Test + fun `click on About invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenAbout = callback, + ) + rule.clickOn(CommonStrings.common_about) + } + } + + @Test + fun `click on Developer settings invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showDeveloperSettings = true, + eventSink = eventsRecorder, + ), + onOpenDeveloperSettings = callback, + ) + rule.clickOn(CommonStrings.common_developer_options) + } + } + + @Test + fun `when showDeveloperSettings is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showDeveloperSettings = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_developer_options)).assertDoesNotExist() + } + + @Test + fun `click on Advanced settings invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenAdvancedSettings = callback, + ) + rule.clickOn(CommonStrings.common_advanced_settings) + } + } + + @Test + fun `click on Labs invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + showLabsItem = true, + eventSink = eventsRecorder, + ), + onOpenLabs = callback, + ) + rule.clickOn(R.string.screen_labs_title) + } + } + + @Test + fun `when showLabsItem is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + showLabsItem = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(R.string.screen_labs_title)).assertDoesNotExist() + } + + @Test + fun `click on Notification invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onOpenNotificationSettings = callback, + ) + rule.clickOn(R.string.screen_notification_settings_title) + } + } + + @Test + fun `click on Blocked users invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + nbOfBlockedUsers = 1, + eventSink = eventsRecorder, + ), + onOpenBlockedUsers = callback, + ) + rule.clickOn(CommonStrings.common_blocked_users) + } + } + + @Test + fun `when nbOfBlockedUsers is 0, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + nbOfBlockedUsers = 0, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.common_blocked_users)).assertDoesNotExist() + } + + @Test + fun `click on Remove this device invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + eventSink = eventsRecorder, + ), + onSignOutClick = callback, + ) + rule.clickOn(CommonStrings.action_signout) + } + } + + @Test + fun `click on Deactivate invokes the expected callback`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + ensureCalledOnce { callback -> + rule.setView( + aPreferencesRootState( + canDeactivateAccount = true, + eventSink = eventsRecorder, + ), + onDeactivateClick = callback, + ) + rule.clickOn(CommonStrings.action_deactivate_account) + } + } + + @Test + fun `when canDeactivateAccount is false, item is not shown`() { + val eventsRecorder = EventsRecorder(expectEvents = false) + rule.setView( + aPreferencesRootState( + canDeactivateAccount = false, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(rule.activity.getString(CommonStrings.action_deactivate_account)).assertDoesNotExist() + } + + @Test + fun `clicking on version sends a PreferencesRootEvents`() { + val version = "VERSION" + val eventsRecorder = EventsRecorder() + rule.setView( + aPreferencesRootState( + version = version, + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithText(version).performClick() + eventsRecorder.assertSingle(PreferencesRootEvent.OnVersionInfoClick) + } +} + +private fun AndroidComposeTestRule.setView( + state: PreferencesRootState, + onBackClick: () -> Unit = EnsureNeverCalled(), + onAddAccountClick: () -> Unit = EnsureNeverCalled(), + onSecureBackupClick: () -> Unit = EnsureNeverCalled(), + onManageAccountClick: (url: String) -> Unit = EnsureNeverCalledWithParam(), + onLinkNewDeviceClick: () -> Unit = EnsureNeverCalled(), + onOpenAnalytics: () -> Unit = EnsureNeverCalled(), + onOpenRageShake: () -> Unit = EnsureNeverCalled(), + onOpenLockScreenSettings: () -> Unit = EnsureNeverCalled(), + onOpenAbout: () -> Unit = EnsureNeverCalled(), + onOpenDeveloperSettings: () -> Unit = EnsureNeverCalled(), + onOpenAdvancedSettings: () -> Unit = EnsureNeverCalled(), + onOpenLabs: () -> Unit = EnsureNeverCalled(), + onOpenNotificationSettings: () -> Unit = EnsureNeverCalled(), + onOpenUserProfile: (MatrixUser) -> Unit = EnsureNeverCalledWithParam(), + onOpenBlockedUsers: () -> Unit = EnsureNeverCalled(), + onSignOutClick: () -> Unit = EnsureNeverCalled(), + onDeactivateClick: () -> Unit = EnsureNeverCalled(), +) { + setContent { + PreferencesRootView( + state = state, + onBackClick = onBackClick, + onAddAccountClick = onAddAccountClick, + onSecureBackupClick = onSecureBackupClick, + onManageAccountClick = onManageAccountClick, + onLinkNewDeviceClick = onLinkNewDeviceClick, + onOpenAnalytics = onOpenAnalytics, + onOpenRageShake = onOpenRageShake, + onOpenLockScreenSettings = onOpenLockScreenSettings, + onOpenAbout = onOpenAbout, + onOpenDeveloperSettings = onOpenDeveloperSettings, + onOpenAdvancedSettings = onOpenAdvancedSettings, + onOpenLabs = onOpenLabs, + onOpenNotificationSettings = onOpenNotificationSettings, + onOpenUserProfile = onOpenUserProfile, + onOpenBlockedUsers = onOpenBlockedUsers, + onSignOutClick = onSignOutClick, + onDeactivateClick = onDeactivateClick, + ) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt index b1e3356fc3..660b071983 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/avatar/AvatarSize.kt @@ -24,7 +24,7 @@ enum class AvatarSize(val dp: Dp) { RoomSelectRoomListItem(36.dp), - UserPreference(56.dp), + UserPreference(52.dp), UserHeader(96.dp), UserListItem(36.dp), diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt index c054b318f3..4d2db383a7 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt @@ -8,16 +8,21 @@ package io.element.android.libraries.designsystem.preview +import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable +import io.element.android.libraries.designsystem.utils.CommonDrawables @Composable fun ElementPreviewDark( showBackground: Boolean = true, - content: @Composable () -> Unit + @DrawableRes + drawableFallbackForImages: Int = CommonDrawables.sample_background, + content: @Composable () -> Unit, ) { ElementPreview( darkTheme = true, showBackground = showBackground, - content = content + drawableFallbackForImages = drawableFallbackForImages, + content = content, ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt index 1c2bdf3cef..19b40f3520 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt @@ -8,16 +8,21 @@ package io.element.android.libraries.designsystem.preview +import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable +import io.element.android.libraries.designsystem.utils.CommonDrawables @Composable fun ElementPreviewLight( showBackground: Boolean = true, - content: @Composable () -> Unit + @DrawableRes + drawableFallbackForImages: Int = CommonDrawables.sample_background, + content: @Composable () -> Unit, ) { ElementPreview( darkTheme = false, showBackground = showBackground, - content = content + drawableFallbackForImages = drawableFallbackForImages, + content = content, ) } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt index 5b44b50ce9..0b9bde0fb9 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.ui.components +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -34,51 +35,34 @@ import io.element.android.libraries.matrix.ui.model.getBestName @Composable fun MatrixUserHeader( - matrixUser: MatrixUser?, - modifier: Modifier = Modifier, - // TODO handle click on this item, to let the user be able to update their profile. - // onClick: () -> Unit, -) { - if (matrixUser == null) { - MatrixUserHeaderPlaceholder(modifier = modifier) - } else { - MatrixUserHeaderContent( - matrixUser = matrixUser, - modifier = modifier, - // onClick = onClick - ) - } -} - -@Composable -private fun MatrixUserHeaderContent( matrixUser: MatrixUser, modifier: Modifier = Modifier, - // onClick: () -> Unit, ) { Row( modifier = modifier - // .clickable(onClick = onClick) .fillMaxWidth() - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically + .padding(horizontal = 16.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically, ) { Avatar( modifier = Modifier - .padding(vertical = 12.dp), + .padding(vertical = 7.dp), avatarData = matrixUser.getAvatarData(size = AvatarSize.UserPreference), avatarType = AvatarType.User, ) - Spacer(modifier = Modifier.width(16.dp)) + Spacer(modifier = Modifier.width(13.dp)) Column( - modifier = Modifier.weight(1f) + modifier = Modifier + .weight(1f) + .padding(vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(2.dp) ) { // Name Text( modifier = Modifier.clipToBounds(), text = matrixUser.getBestName(), maxLines = 1, - style = ElementTheme.typography.fontHeadingSmMedium, + style = ElementTheme.typography.fontHeadingMdRegular, overflow = TextOverflow.Ellipsis, color = ElementTheme.colors.textPrimary, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt deleted file mode 100644 index 08f8a37cc1..0000000000 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * Copyright 2023-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.ui.components - -import androidx.compose.foundation.background -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.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import io.element.android.compound.theme.ElementTheme -import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom -import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.preview.PreviewsDayNight -import io.element.android.libraries.designsystem.theme.placeholderBackground - -@Composable -fun MatrixUserHeaderPlaceholder( - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Box( - modifier = Modifier - .padding(vertical = 12.dp) - .size(AvatarSize.UserPreference.dp) - .background(color = ElementTheme.colors.placeholderBackground, shape = CircleShape) - ) - Spacer(modifier = Modifier.width(16.dp)) - Column( - modifier = Modifier.weight(1f) - ) { - PlaceholderAtom(width = 80.dp, height = 7.dp) - Spacer(modifier = Modifier.height(16.dp)) - PlaceholderAtom(width = 180.dp, height = 6.dp) - } - } -} - -@PreviewsDayNight -@Composable -internal fun MatrixUserHeaderPlaceholderPreview() = ElementPreview { - MatrixUserHeaderPlaceholder() -} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt index 4d5a1cd222..5e9f29496e 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserProvider.kt @@ -20,15 +20,6 @@ open class MatrixUserProvider : PreviewParameterProvider { ) } -open class MatrixUserWithNullProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - aMatrixUser(), - aMatrixUser(displayName = null), - null, - ) -} - open class MatrixUserWithAvatarProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt index cf89074737..ed7fd63435 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt @@ -11,6 +11,8 @@ package io.element.android.libraries.matrix.ui.components import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -23,12 +25,14 @@ fun MatrixUserRow( matrixUser: MatrixUser, modifier: Modifier = Modifier, avatarSize: AvatarSize = AvatarSize.UserListItem, + verticalSpaceWidth: Dp = 12.dp, trailingContent: @Composable (() -> Unit)? = null, ) = UserRow( avatarData = matrixUser.getAvatarData(avatarSize), name = matrixUser.getBestName(), subtext = if (matrixUser.displayName.isNullOrEmpty()) null else matrixUser.userId.value, modifier = modifier, + verticalSpaceWidth = verticalSpaceWidth, trailingContent = trailingContent, ) diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt index 9bcf0b323f..8d236d1a2a 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt @@ -10,13 +10,16 @@ package io.element.android.libraries.matrix.ui.components 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.padding +import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.components.avatar.Avatar @@ -31,22 +34,22 @@ internal fun UserRow( subtext: String?, modifier: Modifier = Modifier, enabled: Boolean = true, + verticalSpaceWidth: Dp = 12.dp, trailingContent: @Composable (() -> Unit)? = null, ) { Row( modifier = modifier .fillMaxWidth() - .padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp), + .padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically ) { Avatar( avatarData = avatarData, avatarType = AvatarType.User, ) + Spacer(modifier = Modifier.width(verticalSpaceWidth)) Column( - modifier = Modifier - .padding(start = 12.dp) - .weight(1f), + modifier = Modifier.weight(1f), ) { // Name Text( From efe76281ad96f4c577672ce93a0a5930bca59db8 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 16 Apr 2026 14:32:48 +0000 Subject: [PATCH 31/44] Update screenshots --- ...res.preferences.impl.root_MultiAccountSection_Day_0_en.png | 3 --- ...s.preferences.impl.root_MultiAccountSection_Night_0_en.png | 3 --- ...res.preferences.impl.root_PreferencesRootViewDark_0_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_1_en.png | 4 ++-- ...res.preferences.impl.root_PreferencesRootViewDark_2_en.png | 3 +++ ...res.preferences.impl.root_PreferencesRootViewDark_3_en.png | 3 +++ ...res.preferences.impl.root_PreferencesRootViewDark_4_en.png | 3 +++ ...res.preferences.impl.root_PreferencesRootViewDark_5_en.png | 3 +++ ...es.preferences.impl.root_PreferencesRootViewLight_0_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_1_en.png | 4 ++-- ...es.preferences.impl.root_PreferencesRootViewLight_2_en.png | 3 +++ ...es.preferences.impl.root_PreferencesRootViewLight_3_en.png | 3 +++ ...es.preferences.impl.root_PreferencesRootViewLight_4_en.png | 3 +++ ...es.preferences.impl.root_PreferencesRootViewLight_5_en.png | 3 +++ ...eatures.preferences.impl.user_UserPreferences_Day_0_en.png | 4 ++-- ...eatures.preferences.impl.user_UserPreferences_Day_1_en.png | 4 ++-- ...eatures.preferences.impl.user_UserPreferences_Day_2_en.png | 3 --- ...tures.preferences.impl.user_UserPreferences_Night_0_en.png | 4 ++-- ...tures.preferences.impl.user_UserPreferences_Night_1_en.png | 4 ++-- ...tures.preferences.impl.user_UserPreferences_Night_2_en.png | 3 --- ...rix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png | 3 --- ...x.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png | 3 --- ...braries.matrix.ui.components_MatrixUserHeader_Day_0_en.png | 4 ++-- ...braries.matrix.ui.components_MatrixUserHeader_Day_1_en.png | 4 ++-- ...aries.matrix.ui.components_MatrixUserHeader_Night_0_en.png | 4 ++-- ...aries.matrix.ui.components_MatrixUserHeader_Night_1_en.png | 4 ++-- 26 files changed, 48 insertions(+), 42 deletions(-) delete mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png delete mode 100644 tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png deleted file mode 100644 index 29b7fa324c..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df19ce5a967143e2cb6d1fe021663f72e36f20c32e912894a2fbad628f03c3e5 -size 53561 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png deleted file mode 100644 index 2ba5234dc6..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_MultiAccountSection_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8fd24e865907b5c9240829710a910e445954bef9b8575f5115a52837e00d817f -size 54591 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png index bc97d5a5c7..4a62c517f0 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:369c835c46e19d3e3171add57055624cf672a9d34109e6c831e0c1bce234c605 -size 39513 +oid sha256:712c1fca10ed7655634d300c03615c6c4dd2f71b74c178398d72fa0427f0d766 +size 41537 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png index c6b82b8385..3ee64a4d09 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3d9f6763de5b844eeace37bedb25b125976625394d69d7843eedb26319e926aa -size 39316 +oid sha256:da47d339d9b8712aa13c394482f8aa5d2e1fb4fcb8eb10df473394bfec1ef507 +size 25980 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png new file mode 100644 index 0000000000..4a56ec8135 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:324ce7d935816d87fea7b70bc7ebaacb0ac1d007b08dba85f03c03a1f045e450 +size 36764 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png new file mode 100644 index 0000000000..f1b39a0d35 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9176ee2b5b78032639d9f51f7680d82f7d3ca916fb587d914f12d075382d65f0 +size 27077 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png new file mode 100644 index 0000000000..5e115162c8 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:821a13ed4effd98ad459e3697a33d9d42500d7f1f46115a97c9b7444303a3bb2 +size 27645 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png new file mode 100644 index 0000000000..31a44423ce --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e457b722fe403205f1394e7347dedb3aba308e48c979ea002399425c9a130fd2 +size 20667 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png index dccf28ff97..d2e319b028 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dce8486726293027aedcdd2e67d10a39a1a2c439ca67d81ae247b60119675ada -size 40385 +oid sha256:2c149288a8ef258f65292f673b9a15ea34910db6d3bfe2402b2a3264227f2b0d +size 42547 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png index 6f2381c6f4..cdd9ef1a41 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93ee581f59c79e03b9c9311765da4c828c5009d14e92f7cca9bbcee418fdfc63 -size 40442 +oid sha256:7ecf19446d8a0cf57431f13cbac9331ff72c93637c1cd1b442ed6330566debb2 +size 26879 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png new file mode 100644 index 0000000000..a83adbff85 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00c7c42f1e6dde16916ae12a889b728c0fb321aa2c3fc6af80ec01d99a3af7a6 +size 37164 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png new file mode 100644 index 0000000000..15c12f4836 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74a4913734d0648115d5056052fa2de8a839bb5a4d2dfdaa3d8ed5f0eef2793d +size 27728 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png new file mode 100644 index 0000000000..3346ad327d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6c20d715bfa287ca0fa78bab1166ff0370b5124455c87f1956e7dc3cb9b3d36 +size 28253 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png new file mode 100644 index 0000000000..c325a4e7b5 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_5_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d5b500d6275bc6ead5e8644b1afb1a0a829e91d4912444e5e0d431322343855 +size 20700 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png index 4c4d183956..c6e079dee2 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ccaa7f88a9e46bdc526bfe3d5c2163bf3d963c0661179db97f62559edfd3189 -size 11042 +oid sha256:0805bac4bf9e1c5bb16b4f81b004bcc952563eef98101d8c9c6e856a414977d0 +size 11219 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png index 0edaae43b6..74bc9743d7 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f37e1587ba12f9b6326b5b7398982fc663ca913da8c0ee83dfbd5e9decbd4362 -size 10906 +oid sha256:b61c5a72e8e63a1775d20717c78d8e68e46c7c22b8e4ab8c24154dc3d48d7d0e +size 11428 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png deleted file mode 100644 index 3a7abad03f..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Day_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b494ecdb4962772dd548339a4ac57be40b273b513697ed6d039d1c905617d54f -size 4987 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png index 741a708fe7..f21d99fffc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcb0063babe7091368af6b5bc7e8929c54ea879bd78043d9128db2dcea9d79fa -size 11191 +oid sha256:070163694fe10b465f2903ce2cc88f9ffc67d9489aa5a4e204cd087fd02b8642 +size 11281 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png index c4e8dfdd29..9413b91e88 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f34e63a88464ddc817d1ffe0324352199ae1821dfa846cceac129a656ece2eb6 -size 10911 +oid sha256:da4e1512cd7a58ede774755b6e3ac427e90c437bbbadaea8479506af776999c3 +size 11323 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png deleted file mode 100644 index 17d1ff9d1b..0000000000 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.user_UserPreferences_Night_2_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f0618a9f769e15b4e682d763224cc1fe0abf62c58f3b9a6b4059153f8805671e -size 4740 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png deleted file mode 100644 index 3a7abad03f..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b494ecdb4962772dd548339a4ac57be40b273b513697ed6d039d1c905617d54f -size 4987 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png deleted file mode 100644 index 17d1ff9d1b..0000000000 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f0618a9f769e15b4e682d763224cc1fe0abf62c58f3b9a6b4059153f8805671e -size 4740 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png index 4c4d183956..c6e079dee2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ccaa7f88a9e46bdc526bfe3d5c2163bf3d963c0661179db97f62559edfd3189 -size 11042 +oid sha256:0805bac4bf9e1c5bb16b4f81b004bcc952563eef98101d8c9c6e856a414977d0 +size 11219 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png index 0edaae43b6..74bc9743d7 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f37e1587ba12f9b6326b5b7398982fc663ca913da8c0ee83dfbd5e9decbd4362 -size 10906 +oid sha256:b61c5a72e8e63a1775d20717c78d8e68e46c7c22b8e4ab8c24154dc3d48d7d0e +size 11428 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png index 741a708fe7..f21d99fffc 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcb0063babe7091368af6b5bc7e8929c54ea879bd78043d9128db2dcea9d79fa -size 11191 +oid sha256:070163694fe10b465f2903ce2cc88f9ffc67d9489aa5a4e204cd087fd02b8642 +size 11281 diff --git a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png index c4e8dfdd29..9413b91e88 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.matrix.ui.components_MatrixUserHeader_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f34e63a88464ddc817d1ffe0324352199ae1821dfa846cceac129a656ece2eb6 -size 10911 +oid sha256:da4e1512cd7a58ede774755b6e3ac427e90c437bbbadaea8479506af776999c3 +size 11323 From 6a4fed2baf4c072e6156901db287e1db593cb1b5 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:30:21 +0300 Subject: [PATCH 32/44] Natural media viewer swiping order (#6431) --- .../impl/viewer/MediaViewerDataSource.kt | 23 ++++++++-- .../impl/viewer/MediaViewerPresenter.kt | 20 ++++++--- .../impl/viewer/MediaViewerPresenterTest.kt | 43 ++++++++++--------- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt index 928e5d9ca8..a9fb5d645c 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerDataSource.kt @@ -120,11 +120,25 @@ class MediaViewerDataSource( */ private fun buildMediaViewerPageList(groupedItems: List) = buildList { // Filter out DateSeparator items, we do not need them for the media viewer - val groupedItemsNoDateSeparator = groupedItems.filterNot { it is MediaItem.DateSeparator } - pagerKeysHandler.accept(groupedItemsNoDateSeparator) - groupedItemsNoDateSeparator.forEach { mediaItem -> + val itemsNoDateSeparator = groupedItems.filterNot { it is MediaItem.DateSeparator } + // Separate loading indicators and media events + val loadingIndicators = itemsNoDateSeparator.filterIsInstance() + val mediaEvents = itemsNoDateSeparator.filterIsInstance() + // Determine backward and forward loading indicators + val backwardLoading = loadingIndicators.find { it.direction == Timeline.PaginationDirection.BACKWARDS } + val forwardLoading = loadingIndicators.find { it.direction == Timeline.PaginationDirection.FORWARDS } + // Build ordered list: backward loading, media events (oldest first), forward loading + // Media events are currently newest first, reverse to get oldest first + val orderedEvents = mediaEvents.reversed() + // Create new list of MediaItem in order: backwardLoading, orderedEvents, forwardLoading + val orderedItems = buildList { + backwardLoading?.let { add(it) } + addAll(orderedEvents) + forwardLoading?.let { add(it) } + } + pagerKeysHandler.accept(orderedItems) + orderedItems.forEach { mediaItem -> when (mediaItem) { - is MediaItem.DateSeparator -> Unit is MediaItem.Event -> { val sourceUrl = mediaItem.mediaSource().safeUrl val localMedia = localMediaStates.getOrPut(sourceUrl) { @@ -148,6 +162,7 @@ class MediaViewerDataSource( pagerKey = pagerKeysHandler.getKey(mediaItem), ) ) + is MediaItem.DateSeparator -> Unit // already filtered out } } }.toImmutableList() diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt index dc0feb70cf..ae581fa8d4 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt @@ -179,15 +179,19 @@ class MediaViewerPresenter( ) { val isRenderingLoadingBackward by remember { derivedStateOf { - currentIndex.intValue == data.value.lastIndex && + currentIndex.intValue == 0 && data.value.size > 1 && - data.value.lastOrNull() is MediaViewerPageData.Loading + data.value.firstOrNull() is MediaViewerPageData.Loading && + (data.value.firstOrNull() as? MediaViewerPageData.Loading)?.direction == Timeline.PaginationDirection.BACKWARDS } } if (isRenderingLoadingBackward) { LaunchedEffect(Unit) { // Observe the loading data vanishing - snapshotFlow { data.value.lastOrNull() is MediaViewerPageData.Loading } + snapshotFlow { + val first = data.value.firstOrNull() + first is MediaViewerPageData.Loading && first.direction == Timeline.PaginationDirection.BACKWARDS + } .distinctUntilChanged() .filter { !it } .onEach { showNoMoreItemsSnackbar() } @@ -203,15 +207,19 @@ class MediaViewerPresenter( ) { val isRenderingLoadingForward by remember { derivedStateOf { - currentIndex.intValue == 0 && + currentIndex.intValue == data.value.lastIndex && data.value.size > 1 && - data.value.firstOrNull() is MediaViewerPageData.Loading + data.value.lastOrNull() is MediaViewerPageData.Loading && + (data.value.lastOrNull() as? MediaViewerPageData.Loading)?.direction == Timeline.PaginationDirection.FORWARDS } } if (isRenderingLoadingForward) { LaunchedEffect(Unit) { // Observe the loading data vanishing - snapshotFlow { data.value.firstOrNull() is MediaViewerPageData.Loading } + snapshotFlow { + val last = data.value.lastOrNull() + last is MediaViewerPageData.Loading && last.direction == Timeline.PaginationDirection.FORWARDS + } .distinctUntilChanged() .filter { !it } .onEach { showNoMoreItemsSnackbar() } diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt index a9d1704bdc..c217ea3306 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt @@ -593,20 +593,20 @@ class MediaViewerPresenterTest { if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), + fileItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) val updatedState = awaitItem() - // User navigate to the first item (forward loading indicator) + // User navigate to the last item (forward loading indicator) updatedState.eventSink( - MediaViewerEvents.OnNavigateTo(0) + MediaViewerEvents.OnNavigateTo(2) ) // data source claims that there is no more items to load forward mediaGalleryDataSource.emitGroupedMediaItems( @@ -614,19 +614,21 @@ class MediaViewerPresenterTest { if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(anImage, aBackwardLoadingIndicator), + fileItems = persistentListOf(aBackwardLoadingIndicator, anImage), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(anImage, aBackwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage), fileItems = persistentListOf(), ) } ) ) - skipItems(1) - val stateWithSnackbar = awaitItem() - assertThat(stateWithSnackbar.snackbarMessage!!.messageResId).isEqualTo(expectedSnackbarResId) + var stateWithSnackbar = awaitItem() + while (stateWithSnackbar.snackbarMessage == null) { + stateWithSnackbar = awaitItem() + } + assertThat(stateWithSnackbar.snackbarMessage.messageResId).isEqualTo(expectedSnackbarResId) } } @@ -665,41 +667,42 @@ class MediaViewerPresenterTest { if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), + fileItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) val updatedState = awaitItem() - // User navigate to the last item (backward loading indicator) + // User navigate to the first item (backward loading indicator) updatedState.eventSink( - MediaViewerEvents.OnNavigateTo(2) + MediaViewerEvents.OnNavigateTo(0) ) - skipItems(1) // data source claims that there is no more items to load backward mediaGalleryDataSource.emitGroupedMediaItems( AsyncData.Success( if (mode is MediaViewerEntryPoint.MediaViewerMode.TimelineFilesAndAudios) { GroupedMediaItems( imageAndVideoItems = persistentListOf(), - fileItems = persistentListOf(aForwardLoadingIndicator, anImage), + fileItems = persistentListOf(anImage, aForwardLoadingIndicator), ) } else { GroupedMediaItems( - imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage), + imageAndVideoItems = persistentListOf(anImage, aForwardLoadingIndicator), fileItems = persistentListOf(), ) } ) ) - skipItems(1) - val stateWithSnackbar = awaitItem() - assertThat(stateWithSnackbar.snackbarMessage!!.messageResId).isEqualTo(expectedSnackbarResId) + var stateWithSnackbar = awaitItem() + while (stateWithSnackbar.snackbarMessage == null) { + stateWithSnackbar = awaitItem() + } + assertThat(stateWithSnackbar.snackbarMessage.messageResId).isEqualTo(expectedSnackbarResId) } } @@ -717,7 +720,7 @@ class MediaViewerPresenterTest { mediaGalleryDataSource.emitGroupedMediaItems( AsyncData.Success( GroupedMediaItems( - imageAndVideoItems = persistentListOf(aForwardLoadingIndicator, anImage, aBackwardLoadingIndicator), + imageAndVideoItems = persistentListOf(aBackwardLoadingIndicator, anImage, aForwardLoadingIndicator), fileItems = persistentListOf(), ) ) From a341a1a59e42321aeb126228bc32f83d8cd7346a Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Fri, 17 Apr 2026 14:48:50 +0200 Subject: [PATCH 33/44] Replace `rustls-platform-verifier-android.aar` with single class (#6610) * Replace the `rustls-platform-verifier-android.aar` with the actual source code * Exclude the platform-verifier code from linters * Add manual update instructions * Exclude from Kover too --- build.gradle.kts | 6 + libraries/matrix/impl/build.gradle.kts | 2 +- .../libs/rustls-platform-verifier-android.aar | Bin 9287 -> 0 bytes ...stls-platform-verifier-android.aar.version | 1 - libraries/rustls-tls/README.md | 9 + libraries/rustls-tls/UPDATED.md | 7 + libraries/rustls-tls/build.gradle.kts | 24 + .../platformverifier/CertificateVerifier.kt | 480 ++++++++++++++++++ .../main/kotlin/extension/KoverExtension.kt | 1 + .../tests/konsist/KonsistLicenseTest.kt | 2 + tools/sdk/update-rustls | 35 -- 11 files changed, 530 insertions(+), 37 deletions(-) delete mode 100644 libraries/matrix/impl/libs/rustls-platform-verifier-android.aar delete mode 100644 libraries/matrix/impl/libs/rustls-platform-verifier-android.aar.version create mode 100644 libraries/rustls-tls/README.md create mode 100644 libraries/rustls-tls/UPDATED.md create mode 100644 libraries/rustls-tls/build.gradle.kts create mode 100644 libraries/rustls-tls/src/main/kotlin/org/rustls/platformverifier/CertificateVerifier.kt delete mode 100755 tools/sdk/update-rustls diff --git a/build.gradle.kts b/build.gradle.kts index f699378d54..92847f39b7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,6 +52,9 @@ allprojects { tasks.withType().configureEach { exclude("io/element/android/tests/konsist/failures/**") + + // This file comes from another project and we want to keep it as close to the original as possible + exclude("org/rustls/platformverifier/**") } // KtLint @@ -79,6 +82,9 @@ allprojects { // This file comes from another project and we want to keep it as close to the original as possible exclude("**/SafeChildrenTransitionScope.kt") + + // This file comes from another project and we want to keep it as close to the original as possible + exclude("org/rustls/platformverifier/**") } } // Dependency check diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index eae96b5cd9..67386cc592 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { } else { debugImplementation(libs.matrix.sdk) } - implementation(files("libs/rustls-platform-verifier-android.aar")) + implementation(projects.libraries.rustlsTls) implementation(projects.appconfig) implementation(projects.libraries.androidutils) diff --git a/libraries/matrix/impl/libs/rustls-platform-verifier-android.aar b/libraries/matrix/impl/libs/rustls-platform-verifier-android.aar deleted file mode 100644 index 8acc8b5fe0b36db4fb45ad8ac4a8f8c3b24fc0c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9287 zcmbulRa6~7v!;!^ySux)JHcHx?(PH$Y#_K3T*AiP9fG^N6WrZhC+Ez?{O4Q$Tut|S zySi6*)#|FtT92v%BoqP|7#tiJ7?}7!fq_B%_X-9E{m-hiczAn2f~o$GN5LV+#AW|3 zzy1mHpTwOk+?;JKluVs$tt{O=SiBt_EaSxyg4wX7o@}I2R$sJ zjHe{n)dRhZi46^1Zk#^$es6GHhht^aGIeYIg}?+fVI5_CLjKRp^z5&m)XBlXLMg$( z5dURn?qKTfZt2cqXX;kvYpF=QUeBXWcX@e9xZJtgsu3lK#q;lQslQ$&=Sr`-9^L*! zVYX9&9_2}x|LJhQV>B)6$E`49Qe}q4G4ltBPhOB zeJQ?HuK?-njmoxlp$%c8^)>?{G7{}6r#Pcjr)KTuR40SER40;vjR|s+RDmyIbC-}6 zKv(edi`~cGFN6Vjvk#qw@cDJ{-AhoJZDkazJeZ7Tt>q$F>$3iBVVL=%RH5Wbd`#Y= zdL$jr596khAHb8I;UisIT&y|TG&(OlmQ5AMRm?B+Z~Y!lp6!rb8?IknNq2q$j}gec zp%Q;2m6)9{ljX~ZzW#cMZ%WKVKjqyw+Pt>SDMJ0{PmXW=@A@8j6Whh-zTQ6ZR*VIB7VzEN z%CC%dunSIYn1a*S5xyKrt+$Z9!w-TOIMtj#YL}qDU**a@QYCrF73VAzPNBsG9uK2b zW_@EZ)?E($c>(E@S5-WUm`CFlbeX-MEoX zIJ!Ub3U_PowLO96{q@c=!D5p6hh##GPCk9_>6-^Vb%gZ0C;HPJc+On)IJX(umUdCg z^Xp4dVf2C%M?~9)w%o;5tIuhn69joka63d#FZ}yf+lvau5~Lb6U0hmCab1_I;5PY; zKK*S{xPLGEMdCL}{ec2Cj3FU?Mv@@!a1&)$BhdWhTT^-91@cG6j~CC((=+#Fw!MAS zB^|~09AD$L;I?lTqA2(h-%21cdz!O>?`Hby1`#NP<>_w)zI40 zUhj?M{w4d2>a6PJ)Ki18Rqg|th3U?zjy7~FBWk43Zb^<*TB*=TbX-o}UK(9VHR8pFyshD`ZYLF|I`X=143hdghUM~A1R`Q=U9y#lV|{2OX>c}nNJQj zudY2kdfjiE9x<7pZY`P{)r6uYXgNX5@$F5bMo4`CrlfTk#uRgznfa`OKA)rV?H%vv z4#Pve;)O(%?%zJ}(+6fr76iW?w!C&|#ZT58Dnu5U8w!y24x93)^L&U!^HW^{cx2Im z;dm2#-fD}g73kz>GG57FmSIreoHwL-S=Q>%*qFttzOp5Kzg+|S2nRQdC7B!FrqzfM zQ2?pc2Tx6yOZ;8e5&~?-X4twQ&O!fy2t^(7zs&N%#inF&{ki6|DzzYmwkdr;kawpl zU$kf9#$;7((rUJ=ny9+t1|vi4C5N`LNc?%)JDJ}W4ST9X*4o_TGgAz7F4G~2hMyVQ z&aR%4$`WA1<0t1%pBsy4HKqs{^~A*;c6FgKAqL|8aj9ZlBFwj;$$tL$ugtFuI!9T| zyrqG}{(U;0kihajb|*F3^w6rBlG-QBu2`7EktkpyRk$ig&-AiA;KUQ?TUSMLolRQm zHaD@I7r)%!#2O^wgk8XFxLe=&-7_OOood+mJcdL(pX2oxQy#sQd#yz-v0WyTW^Thz zLmTL+cA_1mO-|;37ZO%Mqq;@&f{U1h#NCl@8UyAxx#^y^3vDl-ND5RA!d$f_Y}Pbq zg`#?fVqpr|B-;7!?(t}yEK7UCH*EBxDVsF&l^~XK9sijrnrJ-=Q9%oT-TA))6Xw=` zec$O-h}xAE^NBA{y1rw0-QnC+OogsBFH3f0+GbK0#$j8N#Oq9t!ZVr?hR|i`5~)~# zd`cc7R=p<*!ILdh@kJ)EXEQZ0USsxV$i{t4OT^lw!Z}j3myHVk61i&!c=m^fSylim zhERX+yEw5oQEef~M;NL=_`_XiLco%TH?|3w(|OUkCr>z?o^Q959Y zfBsmi35ja1EnP-g8_&|iwz?v$9$8dv@H`@5JUM3S{ zF)_1AZC;NU@PbUI^P%-&JSf4Q4sC&9HC9y=xBL;E-+q;etDSE%2&5*?Sq?xy)A*G< zyR0uuTSxGnecq<}x3+=oD z+0nE>1I3+ zj~88Ga3gBpuC6i30{HHIc!~1oUJ`$w0nOrP(y>c)%MJ|wFF}I*cJCuT^wx_VccT68 z9Y^2sodzFQ>xhazhA}9d_)j@-Q@iN3_qt<=0RnOb!-`v>LstdJ@X2G2;upcYnjgY5 zcyI`@GDH9{Jthigj{vQu-DAzl1Z3oy?X_&775ePHr&oOo6P-l4Gbpf_dUl;Rak^Aj zVkz4d^D9*^3fs+1YJE9L2W>mBx~`r#$22kVD7srN;R;_%+;@lr!n+o1?c6HyL*f|5 zwTFlhjRwU>-vYyX#=9xNt3XN;eqJ6QEx)R>6$Fx6*rlw?Tv8~of9m5I0*;`QHv}h; za;fsVr;KPvoPkD%qToF3nB-2lS+hRsOxOMJ4Iw=(KVRUA(5z^lEU2WFsSVq(02tlfS>z5D*1~~|R$zp+Td3~B%d2XHUI!8>x(rZCy9qLVfr%riS#Pge zqPzkFG*!ZcWNPHa%!F+?xmTDSw=ofjHEZO0^yH|mW0t>Wnf{8;sKCv^bf}8yH^`>8 zh1qUC4?{mDJ)sZ-W^BvN2&p*fc|jd47WU;_-FMz49+!CNhO zZIks{wH7F*#DHe?8HNEH-^>@kudNSnrIxWP&&Zjvy1KR5FLygl-U&lKE$#LnyxRIhtj~D!)$@>OjkiIok8i@>J0KDUzw)wC08wP?(Q=7yq$iEAcOWG@lwv%SmTN< z2iTS}2oxSKC4jgXHGcu&iHa&g!7iY&gB-aTWz|2O`mk+!IM`kS8|M16iwhV+rz2R7 zCNl2hC8s%{llwrWi^7Z0^)*w=AK!*BFA=rxc+*9)On5^>;%Jl0uIA2$6KXAk1d+em ze(f2g&E>Yghmcy4$_K;Hjac^`<9qF&gdlkRrm^bIxyy}@XyoEuu5{V-Cg)IQ=GMb$ z!IlbkjS;AOOvmDe;ShIz@4hmENpx1FgOR0qdq3BpS={Vs1VoX>)Q@+ZO~;F)@rt21-@$76ptsBg1{B*{X)x zY<~1}xhm?*!Q-fTcxJS6E4Wrr0Xc5LuvWqOm8^te_M+dtY(NFJzlm&ym>ur?Dulxl zA1wSSPJ4eMk^7x`KZBRw7-niWILsmXiCVVjlQlrVAH%g12xa9ym8KlUUn-)z0fOUC zhdg=CCZa=sFPf_>j6IZZSYHkdYi?XF7BrDOHyqL&cF^r2TqAJ%{j~*fYDlOKiN$I0 zK=>DZ=SizUviol0zW{~?JJ@QPCwOe=+;?2X2dY571~%q)n|Pt=QAYq1(NOd0d~mK( z)G3Bryv^{a5H7u{C#+51i{or6gG4wveMj}Ejo=&LjA0S>t^@!=H>hzX+1K~lj#|z+ zuSZwmB-AlIH1jQxicwNLYXZK|$&E_2cH);R3bUwM1?lGQIKI{G(3{3!&~k6q{R`o>(FtZiRQ_4|fwEY^ zH8~oT+tGn5<+1G`6p3Oq9%07=&k_Yq~omCupnWKcGG8)75r>UL_pq8Uvy%Q#MjD zN}WH>1GCkG9u)+OG1%lB+2y~vXE z?%uTn%P+~WadnEY8crG2`(1e}@5`s$Kkg%z3b{i?@^jEI1!}{#oE0ZOkVu_jniNu8 znsRi_J5m9dKytXz5cZj*pVkU@kQ0T13iT! zF<`l_q`GsS_a2@`!CkypO^815{E9Qru?;&@xelepo~Mv*mt|XBanKid97;JSLE-qH zjDa)*#GyQzkpyvEh^|WKbVYMqHG5&b!+95JK3SigfEk48HP^8k^JWX)&e?u`AeAcX z61(J?%jj-~ujw(4Q6nLNHQE^If{b-TxSV!rPJ8$1HqBx++T7g~xffI!s?h?r4(2m5 z6p7`*xs@{eU*lx~(Y`RVd$iMsj2G1aA<+;;pr-!MYe6TpGglrT&Q08PyU$UvF@Bl$F)@H7}}IOIu&L z4B%h`t4iqmA6=qk&QqZMH{PUFz3wPV{WpS((5n9Qv@D&d-e0rt?&nQ=u~>+Yu5>fk zzoX=ZjbhF2=2Eh6XJ5~|G1z*rL3aQRjlPn?dP%zrs!Y}os}}pyQOgB132DI`L})-t zYwS7-QTDZfxg?2Xzxnz_RQrQEVX!5+Q`a%i@sZ>W>8X#`=`&LJA z2FB;^&n)qD_fenc*=Zl_YW$o-wwA}01Rs5tIxr3VMQkMo+AM?e0w>9+%2$=*y?13B zEP?l27)g?+(4|;uiyE(ek|-=xlmk1>+6+=EvGf8HRpaJ*D4n&c-#T0~O9rT_gydLF zsapb&S4$rz>h!P|+I_;M@1J~?ajWb_pUSgR*o_e|ihZU1B=gx~bqL`S)MWF$KoGvZ z(?xY5pA^7CTAR@`Ud0lM`0nR{h3L!J<^@qO3Tqlw$c6%!52Ar_=6GGGM>0tXzb@UD z>1bqVt-KqT0iJOTx*QOB)mR9XN!{$g!%rY*dFxMQ88yd3E{+_&HUvoVDg-p_h5Ba1 z{|*nyjckxJX*I_Ej2E0g1vKXZt_FNN|PDa=o{p@8icFbF-#KlXwKR)p9mhJlQE zLr#Zx@4RqA1%+zWZXqfBqwzAK&g`UOZ`^OrU#b*N^vMggJ!(!JSv$72zY-PdQsiY} zexNd6Io7)Xgp7)O+VlRc@W*}L4RNWnY@(XS-T@`AY~rl5d9(`x`~bKxmtZ6KZN8!k zf$*5ft8kb|{RoFFTzH32q7uYS)=_h17zj`N>u_}Y+uGi= zFl-BMb|5}dy-dF8UsyQ-ENnzpK7u<4mGjifIGXfnNe$Dz@KFulbDi)xu%RY!J&q{` zZm;J*Y}u}d^rHG7eZuW*ch1BNuo8-FlKV%7YvBWEaSj?$A~$k3TY4}33kqawJ;6?Y*0B z9OTd`4_Q~!H2d;A@M%#ETJkZo=DB>Nk94WS?F?o8o>zv9;8fGc&M=YDs7I13eyc)${ zoN7=Bv^}{)Z0vSH9!v-odTmA(j0t^txp><^dOU4e zH;1q5=XiYHns4>>y1uh=0+diA!b{p48$u66Wt$@P!!qydp;&=VkHJKEud?EPH;-`W zu>d)a-^a=VMyGJqt)35!h4zh@cn~J?ar8Zf@Al~pD<4MQcV$Ucj-k`eJ|BG&npiUD z)KwHuHD+4n(plYJ#yLh2k_M1gxwsmu`_VL%E!~iZgtI36BI3JdPz_nb_sj&6D2r~EOV>rX*_Z~%28c{)M=*FZwn{)Kyevqq_8DaSYeVV z-IlF6APoIsCh86e_H7nw2CD5`zesd~oC^1q7w{{y!A{Ycc|uHJkHdNO1j*MPAl;Hu zELP=ow^B{NB&NSP=TgQw(XK?60a5oy71LPHVjYITZ)yC!smV2nTaa^n+?h(51z*h! z;5c8W{HtRx7z4F`$>67Lyz7Z0;y6v8>P|(4hwaxX%lk z0`Bgmy7D25g`7D2W%V`E7j(&&*@V*DRTHnRiczyRdWz0zL5wbtPZ2n1s>ssd9W_dG zqch-;96AWqWw7i4j-|55f_C~hMpNAW&r(0tNXJ3^57eWnw^`U%P|*2&Pug9aK@gBR z!&uiVxzik4QkJ)pOyYJ{0v{BpYsxcz?#2bsIgZx}Et1ZkVHv#VgN3 z-JDT3j=G}`95a~9cgdIUvV`=Kx9-bw0DqeB#=r5RbsaWjYWBh3W|*b~Nw=D-kaRZ7 zA;(DEsC?-4?!!5Mi}Q_%CLvLcJQMr>smE$L*hwgLN~liSVTt%!E(%sm#E6#X6f0Av zdMIP%P!<-)f$@rH*ZRINUhk&xx&bde@icptjs9FQE3rSk8M%?QJTv!O{L2d1Wpz%b z#~g3=aph&ax0xj*H)7=uE|UFTR!apH;Kp-MNsX>I0sE-fm&Y3ZS<5aOhf+6hpO|M|NE1 zy$PsB$XhOq&CriRa4j!UaHjcOxz@Hi=RFJMk`*>}jK%Wi8BbK)FPL&M;=8l+m7bGb zj>L6B@|uM7H~vRe{a_-=Z8me04L@zRz4Q(v$7OR2f_a`D##m2Gcbjg1!z~k)Mm!vj zR?iwKttcGAZF@e}(!5iUVuk*a|vF}1N^GRM+zQZ7L0FE4+L zWwA06$&lbP$*|zPFXQ`@oM?S4RNVzOHb9*@5ffU2it2ZN*f8i&+*I6B0a*l}sTSZ8#4JBu3{dy2Y>=u+v~qvy_IVa_@;DaI5}uI18>=X4GRY9;&z&k?Qgvkzm^%Gs<0kT6?s8LJMl3cl#M zsu-ADWaKVyN;>f7Uj~em@sI+E)`oJ1z{b5f_xddh4LH!x)So#N9DdlHLADC5QKFE< znxv21)5a{uT(vspBKJ_5(Oh+QUV$RP~6TyfBYC7QSgeh04i}b~(V&$Ek!jK=gt`qru zuq;(4<*~CB?41dMrR89IR^Ue!?Lz`sIYBMApFCq5;fEoaLz)r2brxkF+b`T^QFEKl zci)=?tmXNY!Fk@4U3T`NPKjJ9QRKbvr5|$B1ybAily6O4gI6y5K;Z?LNi>aF;(SUcK%bFWp)#y<&5WOy1QQSlcH(j?c%`Dde-?F^7 zS>X}VSR;KDc0)izl3Nn>5t!K@DPseYPnRSB_{*>;f=F9)csKeLaPB!p9r zN&K%hopq(ozem!mXwPRwznZt9_$#K~OM27+D-Z$)D%blLHiG=tSkh06T_VoNh$xi4 zVei*J0LC}tKDnZcy}se)2!^(n3~2Z<9L36=QrT%;0!7BMw(-&;Om0#*P9>3vPQo`( z_IabuVL`ntH@l!|i7P3BRjqv^Wm!RN$>KIUfdoISJEL~%OOnN}!X%3T#S;q`Y`wN2 z1?OGMeel+?%u(XsQD5zB_gld6!LM=3m+_EK4s1PU`M}*DZC~23Jzu4e+X4H%1Cw*T z7`slRwpZsnCTAAA#|}FuCbmv?c6JYGo$Q!WR%)DCoWa2w8ey_zfo}l;ZO>lsU+;l8 zPh$bbrC*3Ia9=yVA6L|$n_nM@c2r+2PS;l%U)Aeh5Xrlu^Ecf(&w|jO(3)#s>1cLi zawA`ILHEl(LE*vfMIYf$#{Uz&P}3J$SNw-unEVs}KPgFTiZjbA%dna|JF=SoZ^DGt z%+uDvg4Np1)WX4%)zs9D+0oL&)WX!ml*Pr(*~QY$!`9MWL6OOAoOMiz30{GjVQON! zfqQ{-`oevhrv%H`ERBoqE(Qr^b3ThK8Fuq}#W7 z&btH;um`Yz+zU7a7UcgOkNNk{{~m=w|7HFgmibSY|Ab}!w*wehVG#Ad?f(xt^Pd6! ylS%nM0sf1>`Tr0q|LORj75zVsz7+ot^;K1XhWW2hQ2! { + // Ensure the keystore is loaded. Since all of the trust managers are initialized in a + // `Lazy`, this will only run once. + keystore?.load(null) + + return lazy { createTrustManager(keystore) } + } + + // -- Test only -- + // Ideally, all of this will be optimized out at compile time due to not being accessed + // in release builds. + + @get:Synchronized + private val mockKeystore: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType()) + + @get:Synchronized + private var mockTrustManager: Lazy = + makeLazyTrustManager(mockKeystore) + + @JvmStatic + private fun addMockRoot(root: ByteArray) { + if (!BuildConfig.TEST) { + throw Exception("attempted to add a mock root outside a test!") + } + + val alias = "root_${mockKeystore.size()}" + // Throwing here is fine since test roots should always be well-formed + val cert = certFactory.generateCertificate(ByteArrayInputStream(root)) + mockKeystore.setCertificateEntry(alias, cert) + + reloadMockData() + } + + @JvmStatic + private fun clearMockRoots() { + // Reload to get a completely fresh internal state + mockKeystore.load(null) + reloadMockData() + } + + @JvmStatic + private fun reloadMockData() { + if (mockTrustManager.isInitialized()) { + mockTrustManager = makeLazyTrustManager(mockKeystore) + } + } + + // Get a list of the system's root CAs. + // Function is public for testing only. + @JvmStatic + fun getSystemRootCAs(): List { + val rootCAs = mutableListOf() + + val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) + factory.init(systemKeystore) + + val availableTrustManagers = try { + factory.trustManagers + } catch (e: RuntimeException) { + Log.w(TAG, "exception thrown creating a TrustManager: $e") + return rootCAs + } + + availableTrustManagers.forEach { trustManager -> + if (trustManager is X509TrustManager) { + rootCAs.addAll(trustManager.acceptedIssuers) + } + } + + return rootCAs + } + + // -- End testing requirements -- + + private val certFactory: CertificateFactory = CertificateFactory.getInstance("X.509") + + private var systemTrustAnchorCache = hashSetOf>() + + @get:Synchronized + private var systemCertificateDirectory: File? = System.getenv("ANDROID_ROOT")?.let { rootPath -> + File("$rootPath/etc/security/cacerts") + } + + @get:Synchronized + private val systemKeystore: KeyStore? = try { + KeyStore.getInstance("AndroidCAStore") + } catch (_: KeyStoreException) { + null + } + + @get:Synchronized + private val systemTrustManager: Lazy = + makeLazyTrustManager(systemKeystore) + + @JvmStatic + private fun verifyCertificateChain( + @Suppress("UNUSED_PARAMETER") context: Context, + serverName: String, + authMethod: String, + allowedEkus: Array, + ocspResponse: ByteArray?, + time: Long, + certChain: Array + ): VerificationResult { + // Convert the array of (supposedly) DER bytes into certificates. + val certificateChain = mutableListOf() + certChain.forEach { certBytes -> + val certificate = try { + certFactory.generateCertificate(ByteArrayInputStream(certBytes)) + } catch (e: CertificateException) { + return VerificationResult(StatusCode.InvalidEncoding) + } + certificateChain.add(certificate as X509Certificate) + } + + // Will never throw `ArrayIndexOutOfBoundsException` because `rustls`'s `ServerCertVerifier` trait + // has a mandatory `end_entity` parameter in `verify_server_cert`. + val endEntity = certificateChain[0] + + // Check that the certificate is valid at the point of time provided by `rustls`. + try { + endEntity.checkValidity(Date(time)) + } catch (e: CertificateExpiredException) { + return VerificationResult(StatusCode.Expired) + } catch (e: CertificateNotYetValidException) { + return VerificationResult(StatusCode.Expired) + } + + // Check that this certificate can be used in a TLS server. + if (!verifyCertUsage(endEntity, allowedEkus)) { + return VerificationResult(StatusCode.InvalidExtension) + } + + // Select the trust manager to use. + // + // We select them as follows: + // - If built for release, only use the system trust manager. This should let all test-related + // code be optimized out. + // - If built for tests: + // - If the mock CA store has any values, use the mock trust manager. + // - Otherwise, use the system trust manager. + val (trustManager, keystore) = if (!BuildConfig.TEST) { + val trustManager = + systemTrustManager.value ?: return VerificationResult(StatusCode.Unavailable) + Pair(trustManager, systemKeystore) + } else { + if (mockKeystore.size() != 0) { + val trustManager = mockTrustManager.value!! + Pair(trustManager, mockKeystore) + } else { + val trustManager = + systemTrustManager.value ?: return VerificationResult(StatusCode.Unavailable) + Pair(trustManager, systemKeystore) + } + } + + // Verify that the certificate chain is valid and correct, and nothing more. + // + // NOTE: This does not validate `serverName` is valid for the end-entity certificate. + // That is handled in Rust as Android/Java do not currently provide a RFC 6125 compliant + // hostname verifier. Additionally, even the RFC 2818 verifier is not available until API 24. + // + // `serverName` is only used for pinning/CT requirements. + // + // Returns the "the properly ordered chain used for verification as a list of X509Certificates.", + // meaning a list from end-entity certificate to trust-anchor. + val validChain = try { + trustManager.checkServerTrusted(certificateChain.toTypedArray(), authMethod, serverName) + } catch (e: CertificateException) { + // In test configurations we may see `checkServerTrusted` fail once vendored test + // certificates pass their expiry date. We try to avoid that by using a fixed + // verification time when calling `endEntity.checkValidity` above, however we can't + // fix the time for the `checkServerTrusted` call. + // + // To make diagnosing CI test failures easier we try to find the root cause of + // checkServerTrusted failing, returning a different `StatusCode` as appropriate. + if (BuildConfig.TEST) { + var rootCause: Throwable? = e + while (rootCause?.cause != null && rootCause.cause != rootCause) { + rootCause = rootCause.cause + } + return when (rootCause) { + is CertificateExpiredException, is CertificateNotYetValidException -> VerificationResult( + StatusCode.Expired, + rootCause.toString() + ) + + else -> VerificationResult(StatusCode.UnknownCert, rootCause.toString()) + } + } + // In non-test configurations we should have caught expiry errors earlier and + // can simply return an unknown cert error without digging through the exception + // cause chain. + return VerificationResult(StatusCode.UnknownCert, e.toString()) + } + + // TEST ONLY: Mock test suite cannot attempt to check revocation status if no OSCP data has been stapled, + // because Android requires certificates to an specify OCSP responder for network fetch in this case. + // If in testing w/o OCSP stapled, short-circuit here - only prior checks apply. + if (BuildConfig.TEST && (mockKeystore.size() != 0) && (ocspResponse == null)) { + return VerificationResult(StatusCode.Ok) + } + + // Try to check the revocation status of the cert, if it is supported. + // + // This is supported at >= API 24, but we're supporting 22 (Android 5) for the best + // compatibility. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + // Note: + // + // 1. Android does not provide any way only to attempt to validate revocation from cached + // data like the other platforms do. This means it will always use the network for + // certificates which had no stapled response. + // + // 2: Likely because of 1, Android requires all issued certificates to have some form of + // revocation included in their authority information. This doesn't work universally as + // issuing certificates in use may omit authority access information (for example the + // Let's Encrypt R3 Intermediate Certificate). + // + // Given these constraints, the best option is to only check revocation information + // at the end-entity depth. We will prefer OCSP (to use stapled information if possible). + // If there is no stapled OCSP response, Android may use the network to attempt to fetch + // one. If OCSP checking fails, it may fall back to fetching CRLs. We allow "soft" + // failures, for example transient network errors. + // + // In the case of a non-public root, such as an internal CA or self-signed certificate, + // we opt to skip revocation checks entirely. The only exception is if the server + // provided stapled OCSP data, which is an explicit signal and won't introduce non-ideal + // platform behavior when attempting validation. + // + // This is because these are cases where a user or administrator has explicitly opted to + // trust a certificate they (at least believe) have control over. These certificates rarely + // contain revocation information as well, so these cases don't lose much. + // See https://github.com/rustls/rustls-platform-verifier/issues/69 as well. + if (ocspResponse == null && !isKnownRoot(validChain.last())) { + // Chain validation must have succeeded by this point. + return VerificationResult(StatusCode.Ok) + } + + val parameters = PKIXBuilderParameters(keystore, null) + + val validator = CertPathValidator.getInstance("PKIX") + val revocationChecker = validator.revocationChecker as PKIXRevocationChecker + + revocationChecker.options = EnumSet.of( + PKIXRevocationChecker.Option.SOFT_FAIL, + PKIXRevocationChecker.Option.ONLY_END_ENTITY + ) + + // Use the OCSP data `rustls` provided, if present. + // Its expected that the server only sends revocation data for its own leaf certificate. + // + // If this field is set, then Android will use it and skip any networking to + // attempt a fetch for that certificate. Otherwise, it will attempt to fetch it from the network. + // Ref: https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java;l=694 + ocspResponse?.let { providedResponse -> + revocationChecker.ocspResponses = mapOf(endEntity to providedResponse) + } + + // Use the custom revocation definition. + // "Note that when a `PKIXRevocationChecker` is added to `PKIXParameters`, it clones the `PKIXRevocationChecker`; + // thus any subsequent modifications to the `PKIXRevocationChecker` have no effect." + // - https://developer.android.com/reference/java/security/cert/PKIXRevocationChecker + parameters.certPathCheckers = listOf(revocationChecker) + // "When supplying a revocation checker in this manner, it will be used to check revocation + // irrespective of the setting of the `RevocationEnabled` flag." + // - https://developer.android.com/reference/java/security/cert/PKIXRevocationChecker + parameters.isRevocationEnabled = false + + // Validate the revocation status of the end entity certificate. + try { + validator.validate(certFactory.generateCertPath(validChain), parameters) + } catch (e: CertPathValidatorException) { + // LetsEncrypt no longer include OCSP information (as OCSP is being deprecated) which Android is not + // happy with since it *only* tries OCSP by default. We aren't 100% decided on how to fix this yet for real + // (see https://github.com/rustls/rustls-platform-verifier/pull/179) so for now we implement an out for + // tests to allow regular maintenance to proceed. + if (BuildConfig.TEST && e.reason == CertPathValidatorException.BasicReason.UNSPECIFIED) { + return VerificationResult(StatusCode.Ok) + } + + return VerificationResult(StatusCode.Revoked, e.toString()) + } + } else { + // This is allowed to be skipped since revocation checking is best-effort. + Log.w(TAG, "did not attempt to validate OCSP due to Android version") + } + + return VerificationResult(StatusCode.Ok) + } + + private fun verifyCertUsage(certificate: X509Certificate, allowedEkus: Array): Boolean { + val ekus = try { + certificate.extendedKeyUsage + } + // This should be unreachable, but could happen. + catch (_: CertificateParsingException) { + return false + } catch (_: NullPointerException) { + // According to Chromium's implementation, this can crash when the EKU data is malformed. + Log.w(TAG, "exception handling certificate EKU") + return false + } ?: return true // If the list is empty, we have nothing to do. + + return ekus.any { allowedEkus.contains(it) } + } + + // Android hashes a principal using the first four bytes of its MD5 digest, encoded in + // lowercase hex and reversed. + // + // Ref: https://source.chromium.org/chromium/chromium/src/+/main:net/android/java/src/org/chromium/net/X509Util.java;l=339 + private fun hashPrincipal(principal: X500Principal): String { + val hexDigits = "0123456789abcdef".toCharArray() + val digest = MessageDigest.getInstance("MD5").digest(principal.encoded) + val hexChars = CharArray(8) + + for (i in 0..3) { + // Kotlin doesn't support bitwise operators for bytes, only Int and Long. + val digestByte = digest[3 - i].toInt() + hexChars[2 * i] = hexDigits[(digestByte shr 4) and 0xf] + hexChars[2 * i + 1] = hexDigits[digestByte and 0xf] + } + + return String(hexChars) + } + + // Check if CA root is known or not. + // Known means installed in root CA store, either a preset public CA or a custom one installed by an enterprise/user. + // + // Ref: https://source.chromium.org/chromium/chromium/src/+/main:net/android/java/src/org/chromium/net/X509Util.java;l=351 + fun isKnownRoot(root: X509Certificate): Boolean { + // System keystore and cert directory must be non-null to perform checking + systemKeystore?.let { loadedSystemKeystore -> + systemCertificateDirectory?.let { loadedSystemCertificateDirectory -> + + // Check the in-memory cache first + val key = Pair(root.subjectX500Principal, root.publicKey) + if (systemTrustAnchorCache.contains(key)) { + return true + } + + // System trust anchors are stored under a hash of the principal. + // In case of collisions, append number. + val hash = hashPrincipal(root.subjectX500Principal) + var i = 0 + while (true) { + val alias = "$hash.$i" + + if (!File(loadedSystemCertificateDirectory, alias).exists()) { + break + } + + val anchor = loadedSystemKeystore.getCertificate("system:$alias") + + // It's possible for `anchor` to be `null` if the user deleted a trust anchor. + // Continue iterating as there may be further collisions after the deleted anchor. + if (anchor == null) { + continue + // This should never happen + } else if (anchor !is X509Certificate) { + // SAFETY: This logs a unique identifier (hash value) only in cases where a file within the + // system's root trust store is not a valid X509 certificate (extremely unlikely error). + // The hash doesn't tell us any sensitive information about the invalid cert or reveal any of + // its contents - it just lets us ID the bad file if a user is having TLS failure issues. + Log.e(TAG, "anchor is not a certificate, alias: $alias") + continue + // If subject and public key match, it's a system root. + } else { + if ((root.subjectX500Principal == anchor.subjectX500Principal) && (root.publicKey == anchor.publicKey)) { + systemTrustAnchorCache.add(key) + return true + } + } + + i += 1 + } + } + } + + // Not found in cache or store: non-public + return false + } +} diff --git a/plugins/src/main/kotlin/extension/KoverExtension.kt b/plugins/src/main/kotlin/extension/KoverExtension.kt index 27e44e31b9..5d6b1ddabb 100644 --- a/plugins/src/main/kotlin/extension/KoverExtension.kt +++ b/plugins/src/main/kotlin/extension/KoverExtension.kt @@ -43,6 +43,7 @@ val excludedKoverSubProjects = listOf( ":libraries:core", ":libraries:coroutines", ":libraries:di", + ":libraries:rustls-tls", ":tests:detekt-rules", ":tests:konsist", ":tests:testutils", diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistLicenseTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistLicenseTest.kt index f47621da0e..e7f82292a4 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistLicenseTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistLicenseTest.kt @@ -48,6 +48,7 @@ class KonsistLicenseTest { .files .filter { it.moduleName.startsWith("enterprise").not() && + it.moduleName != "libraries/rustls-tls" && it.nameWithExtension != "locales.kt" && it.name.startsWith("Template ").not() } @@ -78,6 +79,7 @@ class KonsistLicenseTest { .scopeFromProject() .files .filter { + it.moduleName.endsWith("rustls-tls").not() && it.nameWithExtension != "locales.kt" && it.nameWithExtension != "KonsistLicenseTest.kt" && it.name.startsWith("Template ").not() diff --git a/tools/sdk/update-rustls b/tools/sdk/update-rustls deleted file mode 100755 index d8ad883d69..0000000000 --- a/tools/sdk/update-rustls +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -set -e -set -u - -VERSION=${1:-} -if [ -n "$VERSION" ]; then - PACKAGE=rustls-platform-verifier-android==$VERSION -else - PACKAGE=rustls-platform-verifier-android -fi - -cargo install cargo-download -mkdir -p tmp/rustls-platform-verifier-android -cargo download $PACKAGE > tmp/rustls-platform-verifier-android/rustls-platform-verifier-android.gz -ROOT=$(git rev-parse --show-toplevel) - -cd tmp/rustls-platform-verifier-android - -echo "Extracting rustls-platform-verifier-android.aar from \`rustls-platform-verifier-android.gz\`" - -tar -xzvf rustls-platform-verifier-android.gz &> /dev/null -DIR=$(find . -type d -name "rustls-platform-verifier-android-*") -AAR=$(find $DIR -type f -name "*.aar") -cp $AAR $ROOT/libraries/matrix/impl/libs/rustls-platform-verifier-android.aar -cd $ROOT -rm -r tmp/rustls-platform-verifier-android - -echo "Updated rustls-platform-verifier-android.aar using \`$(basename $AAR)\`" > libraries/matrix/impl/libs/rustls-platform-verifier-android.aar.version -cat libraries/matrix/impl/libs/rustls-platform-verifier-android.aar.version From 8182a149d09201dd1ab3f9a89be8afccf13d1dc7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Apr 2026 14:54:53 +0200 Subject: [PATCH 34/44] Live location : ensure it's not sorted randomly --- .../impl/show/LiveLocationShareComparator.kt | 20 ++++++ .../impl/show/ShowLocationPresenter.kt | 56 ++++++++------- .../show/LiveLocationShareComparatorTest.kt | 69 +++++++++++++++++++ .../impl/show/ShowLocationPresenterTest.kt | 2 + .../api/room/location/LiveLocationShare.kt | 2 + .../room/location/LiveLocationSharesFlow.kt | 1 + 6 files changed, 124 insertions(+), 26 deletions(-) create mode 100644 features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparator.kt create mode 100644 features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparator.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparator.kt new file mode 100644 index 0000000000..41b9bea4ca --- /dev/null +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparator.kt @@ -0,0 +1,20 @@ +/* + * 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.show + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.location.LiveLocationShare + +class LiveLocationShareComparator(private val currentUser: UserId) : Comparator { + override fun compare(p0: LiveLocationShare, p1: LiveLocationShare): Int { + val p0IsCurrentUser = p0.userId == currentUser + val p1IsCurrentUser = p1.userId == currentUser + if (p0IsCurrentUser != p1IsCurrentUser) return if (p0IsCurrentUser) -1 else 1 + return p1.startTimestamp.compareTo(p0.startTimestamp) + } +} 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 6b05e473c6..43d3aa6d00 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 @@ -133,35 +133,39 @@ class ShowLocationPresenter( } is ShowLocationMode.Live -> { produceState(persistentListOf()) { + val comparator = LiveLocationShareComparator(currentUser = joinedRoom.sessionId) val liveLocationSharesFlow = joinedRoom.subscribeToLiveLocationShares() val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() } combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members -> - liveShares.mapNotNull { share -> - val lastLocation = share.lastLocation ?: return@mapNotNull null - val location = Location.fromGeoUri(lastLocation.geoUri) ?: return@mapNotNull null - val member = members.find { it.userId == share.userId } - val displayName = member?.getBestName() ?: share.userId.value - val avatarUrl = member?.avatarUrl - val relativeTime = dateFormatter.format(timestamp = lastLocation.timestamp, mode = DateFormatterMode.Full, useRelative = true) - val formattedTimestamp = stringProvider.getString( - CommonStrings.screen_static_location_sheet_timestamp_description, - relativeTime - ) - LocationShareItem( - userId = share.userId, - displayName = displayName, - avatarData = AvatarData( - id = share.userId.value, - name = displayName, - url = avatarUrl, - size = AvatarSize.UserListItem, - ), - formattedTimestamp = formattedTimestamp, - location = location, - isLive = true, - assetType = lastLocation.assetType, - ) - }.toImmutableList() + liveShares + .sortedWith(comparator) + .mapNotNull { share -> + val lastLocation = share.lastLocation ?: return@mapNotNull null + val location = Location.fromGeoUri(lastLocation.geoUri) ?: return@mapNotNull null + val member = members.find { it.userId == share.userId } + val displayName = member?.getBestName() ?: share.userId.value + val avatarUrl = member?.avatarUrl + val relativeTime = dateFormatter.format(timestamp = lastLocation.timestamp, mode = DateFormatterMode.Full, useRelative = true) + val formattedTimestamp = stringProvider.getString( + CommonStrings.screen_static_location_sheet_timestamp_description, + relativeTime + ) + LocationShareItem( + userId = share.userId, + displayName = displayName, + avatarData = AvatarData( + id = share.userId.value, + name = displayName, + url = avatarUrl, + size = AvatarSize.UserListItem, + ), + formattedTimestamp = formattedTimestamp, + location = location, + isLive = true, + assetType = lastLocation.assetType, + ) + } + .toImmutableList() }.collect { value = it } }.value } 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 new file mode 100644 index 0000000000..4042cb4c0c --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/LiveLocationShareComparatorTest.kt @@ -0,0 +1,69 @@ +/* + * 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.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 org.junit.Test + +class LiveLocationShareComparatorTest { + private val currentUser = UserId("@me:matrix.org") + private val comparator = LiveLocationShareComparator(currentUser) + + @Test + fun `compare returns zero when comparing the same current user share`() { + val share = aLiveLocationShare(userId = currentUser, startTimestamp = 123L) + + val result = comparator.compare(share, share) + + assertThat(result).isEqualTo(0) + } + + @Test + fun `compare orders current user share before another user share`() { + val otherShare = aLiveLocationShare(userId = UserId("@alice:matrix.org"), startTimestamp = 200L) + val currentUserShare = aLiveLocationShare(userId = currentUser, startTimestamp = 100L) + + val sortedShares = listOf(otherShare, currentUserShare).sortedWith(comparator) + + assertThat(sortedShares).containsExactly(currentUserShare, otherShare).inOrder() + } + + @Test + fun `compare orders current user shares by newest start timestamp first`() { + val newerShare = aLiveLocationShare(userId = currentUser, startTimestamp = 200L) + val olderShare = aLiveLocationShare(userId = currentUser, startTimestamp = 100L) + + val sortedShares = listOf(olderShare, newerShare).sortedWith(comparator) + + assertThat(sortedShares).containsExactly(newerShare, olderShare).inOrder() + } + + @Test + fun `compare orders non current user shares by newest start timestamp first`() { + val newerShare = aLiveLocationShare(userId = UserId("@alice:matrix.org"), startTimestamp = 200L) + val olderShare = aLiveLocationShare(userId = UserId("@bob:matrix.org"), startTimestamp = 100L) + + val sortedShares = listOf(olderShare, newerShare).sortedWith(comparator) + + 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 5369c441f8..f38e8dae60 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 @@ -469,6 +469,7 @@ 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 { @@ -479,6 +480,7 @@ private fun aLiveLocationShare( timestamp = timestamp, assetType = assetType, ), + startTimestamp = startTimestamp, endTimestamp = endTimestamp, ) } 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 59b2381dbf..3f9c108dc7 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 @@ -17,6 +17,8 @@ data class LiveLocationShare( val userId: UserId, /** The last known location if any. */ val lastLocation: LastLocation?, + /** The timestamp when location sharing started, in milliseconds.*/ + val startTimestamp: Long, /** The timestamp when location sharing ends, in milliseconds. */ val endTimestamp: Long, ) 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 8922cd6627..bae406a137 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 @@ -68,6 +68,7 @@ private fun RustLiveLocationShare.into(): LiveLocationShare { assetType = it.location.asset.into(), ) }, + startTimestamp = startTs.toLong(), endTimestamp = (startTs + timeout).toLong() ) } From 5fb0b3a93d2b14a0b3dc99dbc3ad8a501ee4f066 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 17 Apr 2026 13:45:30 +0000 Subject: [PATCH 35/44] Update screenshots --- ...es.location.api.internal_StaticMapPlaceholder_Day_0_en.png | 4 ++-- ....location.api.internal_StaticMapPlaceholder_Night_0_en.png | 4 ++-- .../images/features.location.api_StaticMapView_Day_0_en.png | 4 ++-- .../images/features.location.api_StaticMapView_Night_0_en.png | 4 ++-- ...ures.location.impl.common.ui_LocationShareRow_Day_0_en.png | 4 ++-- ...es.location.impl.common.ui_LocationShareRow_Night_0_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_1_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_2_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_3_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_4_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_5_en.png | 4 ++-- .../features.location.impl.show_ShowLocationView_Day_6_en.png | 3 +++ .../features.location.impl.show_ShowLocationView_Day_7_en.png | 3 +++ ...eatures.location.impl.show_ShowLocationView_Night_1_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_2_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_3_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_4_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_5_en.png | 4 ++-- ...eatures.location.impl.show_ShowLocationView_Night_6_en.png | 3 +++ ...eatures.location.impl.show_ShowLocationView_Night_7_en.png | 3 +++ ...ine.components.event_TimelineItemLocationView_Day_0_en.png | 4 ++-- ...ine.components.event_TimelineItemLocationView_Day_1_en.png | 4 ++-- ...ine.components.event_TimelineItemLocationView_Day_2_en.png | 4 ++-- ...ine.components.event_TimelineItemLocationView_Day_3_en.png | 3 +++ ...ine.components.event_TimelineItemLocationView_Day_4_en.png | 3 +++ ...e.components.event_TimelineItemLocationView_Night_0_en.png | 4 ++-- ...e.components.event_TimelineItemLocationView_Night_1_en.png | 4 ++-- ...e.components.event_TimelineItemLocationView_Night_2_en.png | 4 ++-- ...e.components.event_TimelineItemLocationView_Night_3_en.png | 3 +++ ...e.components.event_TimelineItemLocationView_Night_4_en.png | 3 +++ ...features.messages.impl.timeline_TimelineView_Day_17_en.png | 4 ++-- .../features.messages.impl.timeline_TimelineView_Day_9_en.png | 4 ++-- ...atures.messages.impl.timeline_TimelineView_Night_17_en.png | 4 ++-- ...eatures.messages.impl.timeline_TimelineView_Night_9_en.png | 4 ++-- 34 files changed, 76 insertions(+), 52 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_6_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_7_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Day_0_en.png index dc7182b71e..aee573a6fc 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c2adbbce73e57c601821ea9b511913b3df0efbdd3d42643fabe0d39655e04e6 -size 438908 +oid sha256:855f37c9ca2dc6ddc9a699e42a1a3c784c26911552174735f46f31ad2588e977 +size 295172 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Night_0_en.png index 41f55afa15..b8ff9c5b98 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.api.internal_StaticMapPlaceholder_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3baf32fc12535ffe246264dfe1f20db1fddddb970f86953e9877251dc3f74d3d -size 173356 +oid sha256:e99b3d1c62e4907f55beefa2414ff6324c62133ab723c13b68c906331e8ee072 +size 118086 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Day_0_en.png index 1735586b26..cedf0b1b7c 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:359960ea4b7be5ff9d766565007291f8585223052483736e17d4532c5f8af0c6 -size 252728 +oid sha256:56a86695d2c25c94a8e79c27c8f525229cc348201073566909f83a681b37ac30 +size 251329 diff --git a/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Night_0_en.png index b18c069686..dea0d3f21c 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.api_StaticMapView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b775500b1fdc6294d94dcb1f07f74c515c3eae31bc55d0faacfd86ff7bd1da3 -size 105526 +oid sha256:0c2b2a7071bd1c21ff706525e2416169507fef364485c651c429baefa15d4c9f +size 104240 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 e48b3cd8ab..cae8f75b66 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:2550638ee12b4181cea31caff0b5838a9cdb3a180c01d1188bc7c2726051b863 -size 16578 +oid sha256:aaafea9efc1000495ee469797239b82193844caa3d6f98c0c3a4344a536a1798 +size 17155 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 0f17f6d6a1..29f70fc9b1 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:c880e4d01495868b3f0689d20d3cbf2050d6261be936421343bc1ac210aabeec -size 15959 +oid sha256:1f113f8979679c0673e4cc1f691140bc570b6826bea23eecc403f2fbfd3f6d09 +size 16460 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_1_en.png index ff0295d9ac..65720f93f6 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:37ccae030071cc4801538dc5c753a6148ce7e465442edcc89877353b7f5675cb -size 37572 +oid sha256:ba0285628cb8f18c5d666e6727b213d3c7674d1782a7364c7b72ff906ad57eff +size 19684 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_2_en.png index 6f440d71d6..26571d8a30 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f57485d56fd4d02731f797762d931c4d738c8693539da612e33403693cd4b08 -size 35976 +oid sha256:ed64e57bea072d5bdf232133c365db043f117e35ef180aa12c9b05bff40a1a92 +size 16437 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_3_en.png index 964ad077b5..ff0295d9ac 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c882f3f9ed18a64ecfa253284bf1dbdad5d38f524258b6463521d5185c1c32a7 -size 31530 +oid sha256:37ccae030071cc4801538dc5c753a6148ce7e465442edcc89877353b7f5675cb +size 37572 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_4_en.png index 46226555db..6f440d71d6 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cdf7b194a075902ab9434e272865293535ef39370fbb9cb172b3cf8774850c73 -size 19104 +oid sha256:5f57485d56fd4d02731f797762d931c4d738c8693539da612e33403693cd4b08 +size 35976 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_5_en.png index ceb1513af6..964ad077b5 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8988c700db517eef71d7f42c8e21ac819f51c92fb88c0c25cb400be7a5326c22 -size 19228 +oid sha256:c882f3f9ed18a64ecfa253284bf1dbdad5d38f524258b6463521d5185c1c32a7 +size 31530 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_6_en.png new file mode 100644 index 0000000000..46226555db --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdf7b194a075902ab9434e272865293535ef39370fbb9cb172b3cf8774850c73 +size 19104 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_7_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_7_en.png new file mode 100644 index 0000000000..ceb1513af6 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Day_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8988c700db517eef71d7f42c8e21ac819f51c92fb88c0c25cb400be7a5326c22 +size 19228 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_1_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_1_en.png index 6c424a1ffe..4e96ed69ce 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a62d7b4716f97f73dddd22fc3ecad30ef159da186ff2f2029772f4574a4f474 -size 36084 +oid sha256:4356f7de986f803b890d3bc95afdefd01e9eb42d775836c647a6d9fafe3bcc4a +size 19189 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_2_en.png index 72196c0b11..cfa358b892 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:10d95b146c51895a0e9e816cf56aa216dfbf77e74ae3da10f9c3fa94468ba9ed -size 34500 +oid sha256:0ce9e4f5911a6dfd35655f362d122f95690a651d7c05e5ef6c4ea0621be2e628 +size 15783 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_3_en.png index da90a76ab1..6c424a1ffe 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:64236eda401891b7a04c9240ed2b9b077b8c08b182b76f454cf0a4376daa740a -size 30345 +oid sha256:6a62d7b4716f97f73dddd22fc3ecad30ef159da186ff2f2029772f4574a4f474 +size 36084 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_4_en.png index eed60f472d..72196c0b11 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da601c01dd487f9c66f78ada91954398e1dcdf699f1ba4f6d8f7661f7b8cc4b7 -size 18715 +oid sha256:10d95b146c51895a0e9e816cf56aa216dfbf77e74ae3da10f9c3fa94468ba9ed +size 34500 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_5_en.png index d3ee3b9e22..da90a76ab1 100644 --- a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ca86fd5eea8c05a52fee801e1ca61c2e4e205ad9874e06d69b1d1f674585f87b -size 18842 +oid sha256:64236eda401891b7a04c9240ed2b9b077b8c08b182b76f454cf0a4376daa740a +size 30345 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_6_en.png new file mode 100644 index 0000000000..eed60f472d --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da601c01dd487f9c66f78ada91954398e1dcdf699f1ba4f6d8f7661f7b8cc4b7 +size 18715 diff --git a/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_7_en.png b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_7_en.png new file mode 100644 index 0000000000..d3ee3b9e22 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.location.impl.show_ShowLocationView_Night_7_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca86fd5eea8c05a52fee801e1ca61c2e4e205ad9874e06d69b1d1f674585f87b +size 18842 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en.png index 57b0b89912..c11e6b978e 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b2dea1019d3de891dd47d0d5e3b1deefeb0938be82afb72b0dc77c1f14596553 -size 144841 +oid sha256:3daba890afd2533e1746f1ffd0c535674a4a238e4591da2a6bcbe31716d26858 +size 143676 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 57b0b89912..bdb2a689ac 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:b2dea1019d3de891dd47d0d5e3b1deefeb0938be82afb72b0dc77c1f14596553 -size 144841 +oid sha256:82ed52f907048490ffb63ea9b33274703c1d92d4131cca0320816cc6949bea5e +size 113727 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 57b0b89912..5d9f6ab2ba 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:b2dea1019d3de891dd47d0d5e3b1deefeb0938be82afb72b0dc77c1f14596553 -size 144841 +oid sha256:ae3a754c163f83e69ab062c8e638a6e620948081d70105ddb00c32dda7c2ba74 +size 119927 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 new file mode 100644 index 0000000000..01d01e6806 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:757d555f948a637952aed4b0ad2745212f6a9ab279d172b0a1649fdf547c5a0c +size 120027 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en.png new file mode 100644 index 0000000000..40384d68cf --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f0cac0a30818ae7a2e1439d403654052bad931c8ba136bdaf37f16272a0b858 +size 20160 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en.png index 74add72a23..b9280ec225 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9305cafe7cca68c9307577533f3b489566c669cbd4fc08c724c8f492bbd75573 -size 58482 +oid sha256:463a2e544b2806f4082c813ec3ba8c6ce0ad0ebcd8ee32666806757a90c248f5 +size 57131 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 74add72a23..6962ed5f4d 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:9305cafe7cca68c9307577533f3b489566c669cbd4fc08c724c8f492bbd75573 -size 58482 +oid sha256:fb0d86877e5d049d618836846cd8ea97b40d1d66e7bd8d50639280fb3e829372 +size 38499 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 74add72a23..7b0ba78a2c 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:9305cafe7cca68c9307577533f3b489566c669cbd4fc08c724c8f492bbd75573 -size 58482 +oid sha256:b41879f5159a126b0641c66bed13470756a914cc038dd239d40d359661784b71 +size 40696 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 new file mode 100644 index 0000000000..8ee52bca11 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_3_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38fa52e6e755d86aa79a029427f04146a3939ac2038cc15717f5aec84ce3be20 +size 40870 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en.png new file mode 100644 index 0000000000..01b3bc1f3f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_4_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09893d3f2bfa2c1f5b99368c21d070ea1aa460d576722410fc2ca85c4eab238c +size 15361 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_17_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_17_en.png index b3255ab5b5..72f4fa03b5 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a87e01d7a14fa40b73c76af0e80c4f2b43ec8cd2f40cb82ef3e321d54f6f341 -size 374820 +oid sha256:4a0827eb23b48bd03fde5078598cb7827459a213ff0a693890581628330f6939 +size 66845 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_9_en.png index b3255ab5b5..adf8d255e3 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Day_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8a87e01d7a14fa40b73c76af0e80c4f2b43ec8cd2f40cb82ef3e321d54f6f341 -size 374820 +oid sha256:a8fa43d296a984d242ed56f7879de4c38f3da94147c365c424248eba2c4ad61d +size 371263 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_17_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_17_en.png index fc5e6d8e98..3ad7246822 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_17_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_17_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ac7741cfc4ec1d8fd9c8c5bab7dc3dcc0ba79932b5a1ab325573b7dd3622c4c -size 153022 +oid sha256:bea070091132156a809da1c185e2f94333e62f8ea9ae7d6d1b789adffb869522 +size 55538 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_9_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_9_en.png index fc5e6d8e98..7b5512dcc7 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_9_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.timeline_TimelineView_Night_9_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3ac7741cfc4ec1d8fd9c8c5bab7dc3dcc0ba79932b5a1ab325573b7dd3622c4c -size 153022 +oid sha256:bcd9e0934b5f6808d58a3d3506641f173c4b223d78c605de09832d3741e8834f +size 149300 From 41f86b492cff64f082349543b6b5dffb1f666b4d Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 17 Apr 2026 16:58:06 +0200 Subject: [PATCH 36/44] Fix test after new property in LiveLocationShare --- .../matrix/impl/room/location/TimedLiveLocationSharesFlowTest.kt | 1 + 1 file changed, 1 insertion(+) 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 6c78fcc51b..41627396ad 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 @@ -141,6 +141,7 @@ private fun aLiveLocationShare( return LiveLocationShare( userId = UserId(userId), lastLocation = null, + startTimestamp = 0L, endTimestamp = endTimestamp, ) } From 09720a01c9527f7831f5bb7a3e923ad8556cc780 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 18:50:20 +0000 Subject: [PATCH 37/44] Update peter-evans/create-pull-request action to v8.1.1 --- .github/workflows/sync-localazy.yml | 2 +- .github/workflows/sync-sas-strings.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sync-localazy.yml b/.github/workflows/sync-localazy.yml index f45a926814..6de0f3b0df 100644 --- a/.github/workflows/sync-localazy.yml +++ b/.github/workflows/sync-localazy.yml @@ -40,7 +40,7 @@ jobs: ./tools/localazy/importSupportedLocalesFromLocalazy.py ./tools/test/generateAllScreenshots.py - name: Create Pull Request for Strings - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: token: ${{ secrets.DANGER_GITHUB_API_TOKEN }} commit-message: Sync Strings from Localazy diff --git a/.github/workflows/sync-sas-strings.yml b/.github/workflows/sync-sas-strings.yml index 7f9dbdee0d..9f7a67cc22 100644 --- a/.github/workflows/sync-sas-strings.yml +++ b/.github/workflows/sync-sas-strings.yml @@ -27,7 +27,7 @@ jobs: - name: Run SAS String script run: ./tools/sas/import_sas_strings.py - name: Create Pull Request for SAS Strings - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: commit-message: Sync SAS Strings title: Sync SAS Strings From f7eaedf8057a5a5eead7203004ce26e49423f5c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:22:22 +0200 Subject: [PATCH 38/44] Merge pull request #6614 from element-hq/renovate/actions-upload-artifact-7.x Update actions/upload-artifact action to v7.0.1 --- .github/workflows/build.yml | 2 +- .github/workflows/build_enterprise.yml | 2 +- .github/workflows/maestro-local.yml | 4 ++-- .github/workflows/nightlyReports.yml | 4 ++-- .github/workflows/quality.yml | 8 ++++---- .github/workflows/release.yml | 6 +++--- .github/workflows/tests.yml | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c60a89e2f6..dd5524c7e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,7 +74,7 @@ jobs: run: ./gradlew :app:assembleGplayDebug app:assembleFDroidDebug -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES - name: Upload debug APKs if: ${{ matrix.variant == 'debug' }} - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: elementx-debug path: | diff --git a/.github/workflows/build_enterprise.yml b/.github/workflows/build_enterprise.yml index aa00b74c44..956655b262 100644 --- a/.github/workflows/build_enterprise.yml +++ b/.github/workflows/build_enterprise.yml @@ -79,7 +79,7 @@ jobs: run: ./gradlew :app:assembleGplayDebug -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES - name: Upload debug Enterprise APKs if: ${{ matrix.variant == 'debug' }} - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: elementx-enterprise-debug path: | diff --git a/.github/workflows/maestro-local.yml b/.github/workflows/maestro-local.yml index 8903ed0e57..9af5c6bc1d 100644 --- a/.github/workflows/maestro-local.yml +++ b/.github/workflows/maestro-local.yml @@ -60,7 +60,7 @@ jobs: ELEMENT_ANDROID_MAPTILER_LIGHT_MAP_ID: ${{ secrets.MAPTILER_LIGHT_MAP_ID }} ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} - name: Upload APK as artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: elementx-apk-maestro path: | @@ -119,7 +119,7 @@ jobs: script: | .github/workflows/scripts/maestro/maestro-local-with-screen-recording.sh app-gplay-x86_64-debug.apk - name: Upload test results - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: test-results path: | diff --git a/.github/workflows/nightlyReports.yml b/.github/workflows/nightlyReports.yml index 314929d801..371c11b3ff 100644 --- a/.github/workflows/nightlyReports.yml +++ b/.github/workflows/nightlyReports.yml @@ -58,7 +58,7 @@ jobs: - name: ✅ Upload kover report if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: kover-results path: | @@ -92,7 +92,7 @@ jobs: run: ./gradlew dependencyCheckAnalyze $CI_GRADLE_ARG_PROPERTIES - name: Upload dependency analysis if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: dependency-analysis path: build/reports/dependency-check-report.html diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 9a191ba15b..6859e78baa 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -120,7 +120,7 @@ jobs: run: ./gradlew :tests:konsist:testDebugUnitTest $CI_GRADLE_ARG_PROPERTIES --no-daemon - name: Upload reports if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: konsist-report path: | @@ -199,7 +199,7 @@ jobs: run: ./gradlew :app:lintGplayDebug :app:lintFdroidDebug lintDebug $CI_GRADLE_ARG_PROPERTIES --continue - name: Upload reports if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: linting-report path: | @@ -240,7 +240,7 @@ jobs: run: ./gradlew detekt $CI_GRADLE_ARG_PROPERTIES --no-daemon - name: Upload reports if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: detekt-report path: | @@ -281,7 +281,7 @@ jobs: run: ./gradlew ktlintCheck $CI_GRADLE_ARG_PROPERTIES - name: Upload reports if: always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ktlint-report path: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 73cba6c8f7..eece5ab0d4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,7 +57,7 @@ jobs: ELEMENT_CALL_RAGESHAKE_URL: ${{ secrets.ELEMENT_CALL_RAGESHAKE_URL }} run: ./gradlew bundleGplayRelease $CI_GRADLE_ARG_PROPERTIES - name: Upload bundle as artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: elementx-app-gplay-bundle-unsigned path: | @@ -95,7 +95,7 @@ jobs: ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} run: ./gradlew bundleGplayRelease $CI_GRADLE_ARG_PROPERTIES - name: Upload bundle as artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: elementx-enterprise-app-gplay-bundle-unsigned path: | @@ -139,7 +139,7 @@ jobs: ELEMENT_ANDROID_MAPTILER_DARK_MAP_ID: ${{ secrets.MAPTILER_DARK_MAP_ID }} run: ./gradlew assembleFdroidRelease $CI_GRADLE_ARG_PROPERTIES - name: Upload apks as artifact - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: elementx-app-fdroid-apks-unsigned path: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0ce66df478..87551c4360 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -77,7 +77,7 @@ jobs: - name: 🚫 Upload kover failed coverage reports if: failure() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: kover-error-report path: | @@ -89,7 +89,7 @@ jobs: - name: 🚫 Upload test results on error if: failure() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: tests-and-screenshot-tests-results path: | From 447f4e51344364ce9a648b4349ca5853519c5fc6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:22:49 +0200 Subject: [PATCH 39/44] Update plugin dependencycheck to v12.2.1 (#6621) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 07442e3c62..67cb3559b8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -261,7 +261,7 @@ 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.0" +dependencycheck = "org.owasp.dependencycheck:12.2.1" 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" } From c35b5811d09920edf0eede9fddf3430f6696de28 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 20 Apr 2026 15:14:10 +0200 Subject: [PATCH 40/44] Restore comment on StaticMapView --- .../io/element/android/features/location/api/StaticMapView.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt b/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt index 3ee0af35af..a61cbe1c24 100644 --- a/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt +++ b/features/location/api/src/main/kotlin/io/element/android/features/location/api/StaticMapView.kt @@ -58,6 +58,9 @@ fun StaticMapView( modifier: Modifier = Modifier, darkMode: Boolean = !ElementTheme.isLightTheme, ) { + // Using BoxWithConstraints to: + // 1) Size the inner Image to the same Dp size of the outer BoxWithConstraints. + // 2) Request the static map image of the exact required size in Px to fill the AsyncImage. BoxWithConstraints( modifier = modifier, contentAlignment = Alignment.Center From 8611b9c69005f75a4cd81ca74d8632572f00a6c4 Mon Sep 17 00:00:00 2001 From: bxdxnn <267911624+bxdxnn@users.noreply.github.com> Date: Mon, 20 Apr 2026 16:36:31 +0300 Subject: [PATCH 41/44] Fix crash when going back to threads list (#6620) * Fix crash when going back to threads list --- .../messages/impl/threads/list/ThreadsListPresenter.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListPresenter.kt index 9d15376e9f..21946510d4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/threads/list/ThreadsListPresenter.kt @@ -8,12 +8,10 @@ package io.element.android.features.messages.impl.threads.list import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.produceState import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import dev.zacsweers.metro.Inject import io.element.android.features.messages.impl.timeline.factories.event.TimelineItemContentFactory import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter @@ -97,12 +95,6 @@ class ThreadsListPresenter( val roomInfo by room.roomInfoFlow.collectAsState() - DisposableEffect(Unit) { - onDispose { - threadsListService.destroy() - } - } - fun handleEvent(event: ThreadsListEvents) { when (event) { ThreadsListEvents.Paginate -> if ((paginationStatus as? ThreadListPaginationStatus.Idle)?.hasMoreToLoad == true) { From f80a140cf9ac779cf0afce50006e23618ccc4f41 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Mon, 20 Apr 2026 16:03:12 +0200 Subject: [PATCH 42/44] Cleanup FetchPushForegroundService (#6577) * Rename `PushHandlingWakeLock` to `FetchPushForegroundServiceManager`. Move the start/stop logic from `FetchPushForegroundService.Companion` to it. * Add more tests using Robolectric. * Remove `FeatureFlags.SyncNotificationsWithWorkManager` and associated code: this should have been removed in one of the previous refactors, since we don't have the 2 ways to sync notifications anymore, everything uses the `WorkManager` --------- Co-authored-by: Benoit Marty --- .../libraries/featureflag/api/FeatureFlags.kt | 8 -- .../push/FetchPushForegroundServiceManager.kt | 27 ++++ .../push/api/push/PushHandlingWakeLock.kt | 26 ---- .../NotificationResultProcessor.kt | 9 -- ...efaultFetchPushForegroundServiceManager.kt | 95 +++++++++++++ .../impl/push/DefaultPushHandlingWakeLock.kt | 33 ----- .../impl/push/FetchPushForegroundService.kt | 78 ++-------- .../FetchPendingNotificationsWorker.kt | 7 +- .../DefaultNotificationResultProcessorTest.kt | 6 - ...ltFetchPushForegroundServiceManagerTest.kt | 134 ++++++++++++++++++ .../FetchPendingNotificationWorkerTest.kt | 6 +- .../FakeFetchPushForegroundServiceManager.kt | 23 +++ .../test/push/FakePushHandlingWakeLock.kt | 24 ---- .../VectorFirebaseMessagingService.kt | 10 +- .../VectorFirebaseMessagingServiceTest.kt | 25 ++-- .../VectorUnifiedPushMessagingReceiver.kt | 14 +- .../VectorUnifiedPushMessagingReceiverTest.kt | 19 ++- 17 files changed, 329 insertions(+), 215 deletions(-) create mode 100644 libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/FetchPushForegroundServiceManager.kt delete mode 100644 libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/PushHandlingWakeLock.kt create mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManager.kt delete mode 100644 libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlingWakeLock.kt create mode 100644 libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManagerTest.kt create mode 100644 libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakeFetchPushForegroundServiceManager.kt delete mode 100644 libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakePushHandlingWakeLock.kt 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 fc06c438aa..c3395d1007 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 @@ -104,14 +104,6 @@ enum class FeatureFlags( defaultValue = { false }, isFinished = false, ), - SyncNotificationsWithWorkManager( - key = "feature.sync_notifications_with_workmanager", - title = "Sync notifications with WorkManager", - description = "Use WorkManager to schedule notification sync tasks when a push is received." + - " This should improve reliability and battery usage.", - defaultValue = { true }, - isFinished = false, - ), QrCodeLogin( key = "feature.qr_code_login", title = "QR Code Login", diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/FetchPushForegroundServiceManager.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/FetchPushForegroundServiceManager.kt new file mode 100644 index 0000000000..be178bbe6c --- /dev/null +++ b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/FetchPushForegroundServiceManager.kt @@ -0,0 +1,27 @@ +/* + * 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.push.api.push + +/** + * A helper to manage the foreground service used to keep the device awake while we schedule and wait for the work to fetch the notification content to run. + */ +interface FetchPushForegroundServiceManager { + /** + * Start the foreground service to acquire the wakelock. If the device is already awake, this method does nothing. + * + * @return true if the service was started, false otherwise (e.g. if the device was already awake or if starting the service failed). + */ + fun start(): Boolean + + /** + * Stop the foreground service to release the wakelock. If the service is not running, this method does nothing. + * + * @return true if the service was stopped, false otherwise (e.g. if the service was not running or if stopping the service failed). + */ + suspend fun stop(): Boolean +} diff --git a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/PushHandlingWakeLock.kt b/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/PushHandlingWakeLock.kt deleted file mode 100644 index 5c76eb1864..0000000000 --- a/libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/push/PushHandlingWakeLock.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.push.api.push - -import kotlin.time.Duration -import kotlin.time.Duration.Companion.minutes - -/** - * Abstraction over wakelocks used for push handling to ensure the device stays awake while we handle the push and schedule and run the work. - */ -interface PushHandlingWakeLock { - /** - * Acquire a wakelock. The wakelock will be held for the given [time] or until [unlock] is called, whichever happens first. - */ - fun lock(time: Duration = 1.minutes) - - /** - * Release the wakelock. If no wakelock is associated with the key, this method does nothing. - */ - suspend fun unlock() -} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResultProcessor.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResultProcessor.kt index e6a3201cbf..0dd2761446 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResultProcessor.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationResultProcessor.kt @@ -13,8 +13,6 @@ import dev.zacsweers.metro.SingleIn import io.element.android.features.call.api.CallType import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.featureflag.api.FeatureFlagService -import io.element.android.libraries.featureflag.api.FeatureFlags 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 @@ -32,7 +30,6 @@ import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEv import io.element.android.libraries.push.impl.push.MutableBatteryOptimizationStore import io.element.android.libraries.push.impl.push.OnNotifiableEventReceived import io.element.android.libraries.push.impl.push.OnRedactedEventReceived -import io.element.android.libraries.push.impl.push.SyncOnNotifiableEvent import io.element.android.libraries.pushstore.api.UserPushStoreFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -60,8 +57,6 @@ class DefaultNotificationResultProcessor( private val userPushStoreFactory: UserPushStoreFactory, private val onRedactedEventReceived: OnRedactedEventReceived, private val onNotifiableEventReceived: OnNotifiableEventReceived, - private val featureFlagService: FeatureFlagService, - private val syncOnNotifiableEvent: SyncOnNotifiableEvent, private val elementCallEntryPoint: ElementCallEntryPoint, private val notificationChannels: NotificationChannels, @AppCoroutineScope private val coroutineScope: CoroutineScope, @@ -215,10 +210,6 @@ class DefaultNotificationResultProcessor( if (nonRingingCallEvents.isNotEmpty()) { onNotifiableEventReceived.onNotifiableEventsReceived(nonRingingCallEvents) } - - if (!featureFlagService.isFeatureEnabled(FeatureFlags.SyncNotificationsWithWorkManager)) { - syncOnNotifiableEvent(results.keys.toList()) - } } private suspend fun handleRingingCallEvent(notifiableEvent: NotifiableRingingCallEvent) { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManager.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManager.kt new file mode 100644 index 0000000000..968661268a --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManager.kt @@ -0,0 +1,95 @@ +/* + * 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.push.impl.push + +import android.app.ActivityManager +import android.content.Context +import android.content.Context.ACTIVITY_SERVICE +import android.content.Context.POWER_SERVICE +import android.content.Intent +import android.os.Build +import android.os.PowerManager +import androidx.core.content.ContextCompat +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.SingleIn +import io.element.android.libraries.core.extensions.runCatchingExceptions +import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.push.api.push.FetchPushForegroundServiceManager +import kotlinx.coroutines.delay +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withTimeoutOrNull +import timber.log.Timber +import kotlin.time.Duration.Companion.seconds + +@ContributesBinding(AppScope::class) +@SingleIn(AppScope::class) +class DefaultFetchPushForegroundServiceManager( + @ApplicationContext private val context: Context, +) : FetchPushForegroundServiceManager { + private val stopMutex = Mutex() + + override fun start(): Boolean { + Timber.d("Acquiring wakelock for push handling, starting service.") + + // Don't start the foreground service if the device is already awake + val powerManager = context.getSystemService(POWER_SERVICE) as PowerManager + if (powerManager.isInteractive) { + Timber.d("Device is already in an interactive state, no need to start FetchPushForegroundService") + return false + } + + val intent = Intent(context, FetchPushForegroundService::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + runCatchingExceptions { ContextCompat.startForegroundService(context, intent) } + .onFailure { throwable -> + Timber.e(throwable, "Failed to start FetchPushForegroundService, notifications may take longer than usual to sync") + } + } else { + context.startService(intent) + } + + return true + } + + override suspend fun stop(): Boolean { + Timber.d("Releasing wakelock used for push handling, stopping service.") + return stopMutex.withLock { + val runningServiceInfo = getRunningServiceInfo(context) + if (runningServiceInfo != null) { + val intent = Intent(context, FetchPushForegroundService::class.java) + // If it's still not running in foreground, it means the service is still starting, + // so we delay the stop to give it time to start and be set as foreground, otherwise we can crash + // with `ForegroundServiceDidNotStartInTimeException`. + var isInForeground = runningServiceInfo.foreground + withTimeoutOrNull(5.seconds) { + while (!isInForeground) { + delay(50) + val updatedServiceInfo = getRunningServiceInfo(context) + if (updatedServiceInfo == null) { + Timber.d("FetchPushForegroundService is no longer running, no need to stop it.") + return@withTimeoutOrNull + } + isInForeground = updatedServiceInfo.foreground == true + } + } ?: Timber.w("FetchPushForegroundService did not start in foreground after 5s, stopping it anyway.") + context.stopService(intent) + } else { + false + } + } + } + + @Suppress("DEPRECATION") + private fun getRunningServiceInfo(context: Context): ActivityManager.RunningServiceInfo? { + val activityManager = context.getSystemService(ACTIVITY_SERVICE) as ActivityManager + return activityManager.getRunningServices(Int.MAX_VALUE) + .firstOrNull { it.service.className == FetchPushForegroundService::class.java.name } + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlingWakeLock.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlingWakeLock.kt deleted file mode 100644 index 27a921c219..0000000000 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlingWakeLock.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.push.impl.push - -import android.content.Context -import dev.zacsweers.metro.AppScope -import dev.zacsweers.metro.ContributesBinding -import dev.zacsweers.metro.SingleIn -import io.element.android.libraries.di.annotations.ApplicationContext -import io.element.android.libraries.push.api.push.PushHandlingWakeLock -import timber.log.Timber -import kotlin.time.Duration - -@ContributesBinding(AppScope::class) -@SingleIn(AppScope::class) -class DefaultPushHandlingWakeLock( - @ApplicationContext private val context: Context, -) : PushHandlingWakeLock { - override fun lock(time: Duration) { - Timber.d("Acquiring wakelock for push handling, starting service.") - FetchPushForegroundService.startIfNeeded(context) - } - - override suspend fun unlock() { - Timber.d("Releasing wakelock used for push handling.") - FetchPushForegroundService.stop(context) - } -} 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 d54b7f5497..2b3587837e 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 @@ -7,32 +7,27 @@ package io.element.android.libraries.push.impl.push -import android.app.ActivityManager import android.app.Service -import android.content.Context import android.content.Intent +import android.content.pm.ServiceInfo import android.os.Build import android.os.IBinder import android.os.PowerManager import androidx.core.app.NotificationCompat +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.api.push.PushHandlingWakeLock 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.delay import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import kotlinx.coroutines.withTimeoutOrNull import timber.log.Timber import kotlin.time.Duration.Companion.minutes -import kotlin.time.Duration.Companion.seconds private const val NOTIFICATION_ID = 1001 @@ -48,7 +43,6 @@ class FetchPushForegroundService : Service() { } @Inject lateinit var notificationChannels: NotificationChannels - @Inject lateinit var pushHandlingWakeLock: PushHandlingWakeLock @Inject @AppCoroutineScope lateinit var coroutineScope: CoroutineScope private val wakelock: PowerManager.WakeLock by lazy { @@ -78,8 +72,13 @@ class FetchPushForegroundService : Service() { // Try to start the service in foreground. This can fail, even in cases where it's supposed to work according to the docs. // In those cases we catch the exception and handle the failure so we don't try to start the wakelock or stop the service // from running in foreground later. + val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE + } else { + 0 + } runCatchingExceptions { - startForeground(NOTIFICATION_ID, notificationCompat) + ServiceCompat.startForeground(this, NOTIFICATION_ID, notificationCompat, serviceType) } .onSuccess { isOnForeground = true @@ -116,7 +115,7 @@ class FetchPushForegroundService : Service() { override fun stopService(intent: Intent?): Boolean { if (isOnForeground) { wakelock.release() - stopForeground(STOP_FOREGROUND_REMOVE) + ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) } return super.stopService(intent) @@ -131,64 +130,7 @@ class FetchPushForegroundService : Service() { Timber.d("onTimeoutAction, calledByTheSystem: $calledByTheSystem, isOnForeground: $isOnForeground") if (isOnForeground) { Timber.d("Wakelock timeout reached, stopping FetchPushForegroundService") - coroutineScope.launch { pushHandlingWakeLock.unlock() } - } - } - - companion object { - private val stopMutex = Mutex() - - fun startIfNeeded(context: Context) { - // Don't start the foreground service if the device is already awake - val powerManager = context.getSystemService(POWER_SERVICE) as PowerManager - if (powerManager.isInteractive) return - - start(context) - } - - fun start(context: Context) { - val intent = Intent(context, FetchPushForegroundService::class.java) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - runCatchingExceptions { context.startForegroundService(intent) } - .onFailure { throwable -> - Timber.e( - throwable, - "Failed to start FetchPushForegroundService, notifications may take longer than usual to sync" - ) - } - } else { - context.startService(intent) - } - } - - suspend fun stop(context: Context) = stopMutex.withLock { - val runningServiceInfo = getRunningServiceInfo(context) - if (runningServiceInfo != null) { - val intent = Intent(context, FetchPushForegroundService::class.java) - // If it's still not running in foreground, it means the service is still starting, - // so we delay the stop to give it time to start and be set as foreground, otherwise we can crash - // with `ForegroundServiceDidNotStartInTimeException`. - var isInForeground = runningServiceInfo.foreground - withTimeoutOrNull(5.seconds) { - while (!isInForeground) { - delay(50) - val updatedServiceInfo = getRunningServiceInfo(context) - if (updatedServiceInfo == null) { - Timber.d("FetchPushForegroundService is no longer running, no need to stop it.") - return@withTimeoutOrNull - } - isInForeground = updatedServiceInfo.foreground == true - } - } ?: Timber.w("FetchPushForegroundService did not start in foreground after 5s, stopping it anyway.") - context.stopService(intent) - } - } - - @Suppress("DEPRECATION") - private fun getRunningServiceInfo(context: Context): ActivityManager.RunningServiceInfo? { - val activityManager = context.getSystemService(ACTIVITY_SERVICE) as ActivityManager - return activityManager.getRunningServices(Int.MAX_VALUE) - .firstOrNull { it.service.className == FetchPushForegroundService::class.java.name } + 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 ec57582529..c18a0015aa 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 @@ -25,7 +25,7 @@ import io.element.android.libraries.matrix.api.auth.SessionRestorationException import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.exception.ClientException import io.element.android.libraries.matrix.api.exception.isNetworkError -import io.element.android.libraries.push.api.push.PushHandlingWakeLock +import io.element.android.libraries.push.api.push.FetchPushForegroundServiceManager import io.element.android.libraries.push.impl.db.PushRequest import io.element.android.libraries.push.impl.history.PushHistoryService import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver @@ -58,7 +58,7 @@ class FetchPendingNotificationsWorker( private val resultProcessor: NotificationResultProcessor, private val analyticsService: AnalyticsService, private val systemClock: SystemClock, - private val pushHandlingWakeLock: PushHandlingWakeLock, + private val fetchPushForegroundServiceManager: FetchPushForegroundServiceManager, ) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { Timber.d("FetchNotificationsWorker started") @@ -67,7 +67,8 @@ class FetchPendingNotificationsWorker( inputData.getString(SyncPendingNotificationsRequestBuilder.SESSION_ID)?.let(::SessionId) }.getOrNull() ?: return Result.failure() - pushHandlingWakeLock.unlock() + // We can stop the foreground service and unlock the wakelock, since the work is now running and the device should be kept awake + fetchPushForegroundServiceManager.stop() // Fetch pending requests in the last 24 hours val fetchSince = Instant.fromEpochMilliseconds(systemClock.epochMillis()).minus(1.days) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationResultProcessorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationResultProcessorTest.kt index 5a0d95c017..6acb375bac 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationResultProcessorTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotificationResultProcessorTest.kt @@ -10,7 +10,6 @@ package io.element.android.libraries.push.impl.notifications import com.google.common.truth.Truth.assertThat import io.element.android.features.call.api.CallType import io.element.android.features.call.test.FakeElementCallEntryPoint -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 @@ -34,7 +33,6 @@ import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEv import io.element.android.libraries.push.impl.push.FakeMutableBatteryOptimizationStore import io.element.android.libraries.push.impl.push.FakeOnNotifiableEventReceived import io.element.android.libraries.push.impl.push.FakeOnRedactedEventReceived -import io.element.android.libraries.push.impl.push.SyncOnNotifiableEvent import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.lambda.any @@ -289,8 +287,6 @@ class DefaultNotificationResultProcessorTest { userPushStoreFactory: FakeUserPushStoreFactory = FakeUserPushStoreFactory(), onRedactedEventReceived: (List) -> Unit = {}, onNotifiableEventsReceived: (List) -> Unit = {}, - featureFlagService: FakeFeatureFlagService = FakeFeatureFlagService(), - syncOnNotifiableEvent: SyncOnNotifiableEvent = {}, elementCallEntryPoint: FakeElementCallEntryPoint = FakeElementCallEntryPoint(), notificationChannels: FakeNotificationChannels = FakeNotificationChannels(), coroutineScope: CoroutineScope = backgroundScope, @@ -301,8 +297,6 @@ class DefaultNotificationResultProcessorTest { userPushStoreFactory = userPushStoreFactory, onRedactedEventReceived = FakeOnRedactedEventReceived(onRedactedEventReceived), onNotifiableEventReceived = FakeOnNotifiableEventReceived(onNotifiableEventsReceived), - featureFlagService = featureFlagService, - syncOnNotifiableEvent = syncOnNotifiableEvent, elementCallEntryPoint = elementCallEntryPoint, notificationChannels = notificationChannels, coroutineScope = coroutineScope, diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManagerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManagerTest.kt new file mode 100644 index 0000000000..63307634f3 --- /dev/null +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultFetchPushForegroundServiceManagerTest.kt @@ -0,0 +1,134 @@ +/* + * 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.push.impl.push + +import android.app.ActivityManager +import android.content.ComponentName +import android.content.Context.ACTIVITY_SERVICE +import android.content.Context.POWER_SERVICE +import android.os.PowerManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.async +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.withTimeout +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.Shadows +import org.robolectric.shadows.ShadowActivityManager +import org.robolectric.shadows.ShadowPowerManager +import kotlin.time.Duration.Companion.seconds + +@RunWith(AndroidJUnit4::class) +class DefaultFetchPushForegroundServiceManagerTest { + @Test + fun `start should start the service if the device is not interactive`() { + val manager = createDefaultFetchPushForegroundServiceManager() + + getShadowPowerManager().turnScreenOn(false) + + assertThat(manager.start()).isTrue() + } + + @Test + fun `start won't start the service if the device is interactive`() { + val manager = createDefaultFetchPushForegroundServiceManager() + + getShadowPowerManager().turnScreenOn(true) + + assertThat(manager.start()).isFalse() + } + + @Test + fun `stop will stop the service if it's running`() = runTest { + val manager = createDefaultFetchPushForegroundServiceManager() + + // Start the service first + getShadowPowerManager().turnScreenOn(false) + manager.start() + + getShadowActivityManager().setServices( + listOf( + ActivityManager.RunningServiceInfo().apply { + service = ComponentName(InstrumentationRegistry.getInstrumentation().context, FetchPushForegroundService::class.java) + foreground = true + } + ) + ) + + assertThat(manager.stop()).isTrue() + } + + @Test + fun `stop will eventually stop the service once it's on foreground`() = runTest { + val manager = createDefaultFetchPushForegroundServiceManager() + + // Start the service first + getShadowPowerManager().turnScreenOn(false) + manager.start() + + // The service is started, but not yet in foreground + getShadowActivityManager().setServices( + listOf( + ActivityManager.RunningServiceInfo().apply { + service = ComponentName(InstrumentationRegistry.getInstrumentation().context, FetchPushForegroundService::class.java) + foreground = false + } + ) + ) + + // We call stop, which won't stop the service yet since it's not in foreground + val future = async { manager.stop() } + + // Then we set the service as running in foreground, which should allow the stop to complete + getShadowActivityManager().setServices( + listOf( + ActivityManager.RunningServiceInfo().apply { + service = ComponentName(InstrumentationRegistry.getInstrumentation().context, FetchPushForegroundService::class.java) + foreground = true + } + ) + ) + + val stopped = withTimeout(5.seconds) { future.await() } + assertThat(stopped).isTrue() + } + + @Test + fun `stop will not stop the service if it's stopped`() = runTest { + val manager = createDefaultFetchPushForegroundServiceManager() + + // Set some fake running service data, even if the service is not really running + getShadowActivityManager().setServices( + listOf( + ActivityManager.RunningServiceInfo().apply { + service = ComponentName(InstrumentationRegistry.getInstrumentation().context, FetchPushForegroundService::class.java) + foreground = true + } + ) + ) + + // Since the service was not really running, it was not stopped + assertThat(manager.stop()).isFalse() + } + + private fun createDefaultFetchPushForegroundServiceManager() = DefaultFetchPushForegroundServiceManager( + context = InstrumentationRegistry.getInstrumentation().context, + ) + + private fun getShadowPowerManager(): ShadowPowerManager { + val powerManager = InstrumentationRegistry.getInstrumentation().context.getSystemService(POWER_SERVICE) as PowerManager + return Shadows.shadowOf(powerManager) + } + + private fun getShadowActivityManager(): ShadowActivityManager { + val activityManager = InstrumentationRegistry.getInstrumentation().context.getSystemService(ACTIVITY_SERVICE) as ActivityManager + return Shadows.shadowOf(activityManager) + } +} diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationWorkerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationWorkerTest.kt index 8168019a99..c0fa5d3442 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationWorkerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/workmanager/FetchPendingNotificationWorkerTest.kt @@ -28,7 +28,7 @@ import io.element.android.libraries.push.impl.notifications.FakeNotificationResu import io.element.android.libraries.push.impl.notifications.fixtures.aPushRequest import io.element.android.libraries.push.impl.notifications.model.ResolvedPushEvent import io.element.android.libraries.push.impl.push.SyncOnNotifiableEvent -import io.element.android.libraries.push.test.push.FakePushHandlingWakeLock +import io.element.android.libraries.push.test.push.FakeFetchPushForegroundServiceManager import io.element.android.libraries.workmanager.api.WorkManagerRequestBuilder import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory import io.element.android.services.analytics.test.FakeAnalyticsService @@ -239,7 +239,7 @@ class FetchPendingNotificationWorkerTest { pushHistoryService: FakePushHistoryService = FakePushHistoryService(), resultProcessor: FakeNotificationResultProcessor = FakeNotificationResultProcessor(), systemClock: FakeSystemClock = FakeSystemClock(), - pushHandlingWakeLock: FakePushHandlingWakeLock = FakePushHandlingWakeLock(), + pushHandlingWakeLock: FakeFetchPushForegroundServiceManager = FakeFetchPushForegroundServiceManager(), ) = FetchPendingNotificationsWorker( params = createWorkerParams(workDataOf("session_id" to input)), context = InstrumentationRegistry.getInstrumentation().context, @@ -250,7 +250,7 @@ class FetchPendingNotificationWorkerTest { pushHistoryService = pushHistoryService, resultProcessor = resultProcessor, systemClock = systemClock, - pushHandlingWakeLock = pushHandlingWakeLock, + fetchPushForegroundServiceManager = pushHandlingWakeLock, ) private fun TestScope.createWorkerParams( diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakeFetchPushForegroundServiceManager.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakeFetchPushForegroundServiceManager.kt new file mode 100644 index 0000000000..d0128b4a09 --- /dev/null +++ b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakeFetchPushForegroundServiceManager.kt @@ -0,0 +1,23 @@ +/* + * 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.push.test.push + +import io.element.android.libraries.push.api.push.FetchPushForegroundServiceManager + +class FakeFetchPushForegroundServiceManager( + private val lock: () -> Boolean = { true }, + private val unlock: () -> Boolean = { true }, +) : FetchPushForegroundServiceManager { + override fun start(): Boolean { + return lock.invoke() + } + + override suspend fun stop(): Boolean { + return unlock.invoke() + } +} diff --git a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakePushHandlingWakeLock.kt b/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakePushHandlingWakeLock.kt deleted file mode 100644 index 077c8f661e..0000000000 --- a/libraries/push/test/src/main/kotlin/io/element/android/libraries/push/test/push/FakePushHandlingWakeLock.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.push.test.push - -import io.element.android.libraries.push.api.push.PushHandlingWakeLock -import kotlin.time.Duration - -class FakePushHandlingWakeLock( - private val lock: (time: Duration) -> Unit = {}, - private val unlock: () -> Unit = {}, -) : PushHandlingWakeLock { - override fun lock(time: Duration) { - lock.invoke(time) - } - - override suspend fun unlock() { - unlock.invoke() - } -} diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt index 3961f1f591..975a3c75ca 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingService.kt @@ -15,7 +15,7 @@ import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.push.api.push.PushHandlingWakeLock +import io.element.android.libraries.push.api.push.FetchPushForegroundServiceManager import io.element.android.libraries.pushproviders.api.PushHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -27,7 +27,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { @Inject lateinit var firebaseNewTokenHandler: FirebaseNewTokenHandler @Inject lateinit var pushParser: FirebasePushParser @Inject lateinit var pushHandler: PushHandler - @Inject lateinit var pushHandlingWakeLock: PushHandlingWakeLock + @Inject lateinit var fetchPushForegroundServiceManager: FetchPushForegroundServiceManager @AppCoroutineScope @Inject lateinit var coroutineScope: CoroutineScope @@ -49,7 +49,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { val isHighPriority = message.priority == PRIORITY_HIGH if (isHighPriority) { // Acquire wakelock to ensure the device stays awake while we handle the push and schedule and run the work - pushHandlingWakeLock.lock() + fetchPushForegroundServiceManager.start() } coroutineScope.launch { @@ -63,7 +63,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { }, ) if (isHighPriority) { - pushHandlingWakeLock.unlock() + fetchPushForegroundServiceManager.stop() } } else { val handled = pushHandler.handle( @@ -73,7 +73,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { // If we failed to handle the push, we should release the wakelock early to avoid keeping the device awake for too long. if (!handled && isHighPriority) { - pushHandlingWakeLock.unlock() + fetchPushForegroundServiceManager.stop() } } } diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingServiceTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingServiceTest.kt index 798328e626..a04c961ebb 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingServiceTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/VectorFirebaseMessagingServiceTest.kt @@ -15,7 +15,7 @@ import com.google.firebase.messaging.RemoteMessage 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_SECRET -import io.element.android.libraries.push.test.push.FakePushHandlingWakeLock +import io.element.android.libraries.push.test.push.FakeFetchPushForegroundServiceManager import io.element.android.libraries.push.test.test.FakePushHandler import io.element.android.libraries.pushproviders.api.PushData import io.element.android.libraries.pushproviders.api.PushHandler @@ -29,7 +29,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner -import kotlin.time.Duration @RunWith(RobolectricTestRunner::class) class VectorFirebaseMessagingServiceTest { @@ -81,11 +80,11 @@ class VectorFirebaseMessagingServiceTest { @Test fun `test pushHandler returning true locks and does not unlock the wakelock so it continues running`() = runTest { - val lockLambda = lambdaRecorder { _ -> } - val unlockLambda = lambdaRecorder { } + val lockLambda = lambdaRecorder { true } + val unlockLambda = lambdaRecorder { true } val vectorFirebaseMessagingService = createVectorFirebaseMessagingService( pushHandler = FakePushHandler(handleResult = { _, _ -> true }), - pushHandlingWakeLock = FakePushHandlingWakeLock( + pushHandlingWakeLock = FakeFetchPushForegroundServiceManager( lock = lockLambda, unlock = unlockLambda ) @@ -113,11 +112,11 @@ class VectorFirebaseMessagingServiceTest { @Test fun `test pushHandler returning false locks and unlocks the wakelock early`() = runTest { - val lockLambda = lambdaRecorder { _ -> } - val unlockLambda = lambdaRecorder { } + val lockLambda = lambdaRecorder { true } + val unlockLambda = lambdaRecorder { true } val vectorFirebaseMessagingService = createVectorFirebaseMessagingService( pushHandler = FakePushHandler(handleResult = { _, _ -> false }), - pushHandlingWakeLock = FakePushHandlingWakeLock( + pushHandlingWakeLock = FakeFetchPushForegroundServiceManager( lock = lockLambda, unlock = unlockLambda ) @@ -145,11 +144,11 @@ class VectorFirebaseMessagingServiceTest { @Test fun `test pushHandler with a remote message with normal priority won't lock the wakelock`() = runTest { - val lockLambda = lambdaRecorder { _ -> } - val unlockLambda = lambdaRecorder { } + val lockLambda = lambdaRecorder { true } + val unlockLambda = lambdaRecorder { true } val vectorFirebaseMessagingService = createVectorFirebaseMessagingService( pushHandler = FakePushHandler(handleResult = { _, _ -> false }), - pushHandlingWakeLock = FakePushHandlingWakeLock( + pushHandlingWakeLock = FakeFetchPushForegroundServiceManager( lock = lockLambda, unlock = unlockLambda ) @@ -186,14 +185,14 @@ class VectorFirebaseMessagingServiceTest { private fun TestScope.createVectorFirebaseMessagingService( firebaseNewTokenHandler: FirebaseNewTokenHandler = FakeFirebaseNewTokenHandler(), pushHandler: PushHandler = FakePushHandler(), - pushHandlingWakeLock: FakePushHandlingWakeLock = FakePushHandlingWakeLock(), + pushHandlingWakeLock: FakeFetchPushForegroundServiceManager = FakeFetchPushForegroundServiceManager(), ): VectorFirebaseMessagingService { return VectorFirebaseMessagingService().apply { this.firebaseNewTokenHandler = firebaseNewTokenHandler this.pushParser = FirebasePushParser() this.pushHandler = pushHandler this.coroutineScope = this@createVectorFirebaseMessagingService - this.pushHandlingWakeLock = pushHandlingWakeLock + this.fetchPushForegroundServiceManager = pushHandlingWakeLock } } } diff --git a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt index 363400ba13..4288f2b6b8 100644 --- a/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt +++ b/libraries/pushproviders/unifiedpush/src/main/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiver.kt @@ -14,7 +14,7 @@ import dev.zacsweers.metro.Inject import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.di.annotations.AppCoroutineScope -import io.element.android.libraries.push.api.push.PushHandlingWakeLock +import io.element.android.libraries.push.api.push.FetchPushForegroundServiceManager import io.element.android.libraries.pushproviders.api.PushHandler import io.element.android.libraries.pushproviders.unifiedpush.registration.EndpointRegistrationHandler import io.element.android.libraries.pushproviders.unifiedpush.registration.RegistrationResult @@ -38,7 +38,7 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { @Inject lateinit var newGatewayHandler: UnifiedPushNewGatewayHandler @Inject lateinit var removedGatewayHandler: UnifiedPushRemovedGatewayHandler @Inject lateinit var endpointRegistrationHandler: EndpointRegistrationHandler - @Inject lateinit var pushHandlingWakeLock: PushHandlingWakeLock + @Inject lateinit var fetchPushForegroundServiceManager: FetchPushForegroundServiceManager @AppCoroutineScope @Inject lateinit var coroutineScope: CoroutineScope @@ -59,8 +59,8 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { * @param instance connection, for multi-account */ override fun onMessage(context: Context, message: PushMessage, instance: String) { - // Acquire wakelock to ensure the device stays awake while we handle the push and schedule and run the work - pushHandlingWakeLock.lock() + // Start the foreground service to ensure the device stays awake while we handle the push and schedule and run the work. + fetchPushForegroundServiceManager.start() Timber.tag(loggerTag.value).d("New message, decrypted: ${message.decrypted}") coroutineScope.launch { @@ -71,16 +71,16 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { providerInfo = "${UnifiedPushConfig.NAME} - $instance", data = String(message.content), ) - pushHandlingWakeLock.unlock() + fetchPushForegroundServiceManager.stop() } else { val handled = pushHandler.handle( pushData = pushData, providerInfo = "${UnifiedPushConfig.NAME} - $instance", ) - // If we failed to handle the push, we should release the wakelock early to avoid keeping the device awake for too long. + // If we failed to handle the push, we should stop the foreground service early to avoid keeping the device awake for too long. if (!handled) { - pushHandlingWakeLock.unlock() + fetchPushForegroundServiceManager.stop() } } } diff --git a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiverTest.kt b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiverTest.kt index ef81c647b3..cb23289c85 100644 --- a/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiverTest.kt +++ b/libraries/pushproviders/unifiedpush/src/test/kotlin/io/element/android/libraries/pushproviders/unifiedpush/VectorUnifiedPushMessagingReceiverTest.kt @@ -18,7 +18,7 @@ import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_SECRET -import io.element.android.libraries.push.test.push.FakePushHandlingWakeLock +import io.element.android.libraries.push.test.push.FakeFetchPushForegroundServiceManager import io.element.android.libraries.push.test.test.FakePushHandler import io.element.android.libraries.pushproviders.api.PushData import io.element.android.libraries.pushproviders.api.PushHandler @@ -39,7 +39,6 @@ import org.unifiedpush.android.connector.FailedReason import org.unifiedpush.android.connector.data.PublicKeySet import org.unifiedpush.android.connector.data.PushEndpoint import org.unifiedpush.android.connector.data.PushMessage -import kotlin.time.Duration @RunWith(RobolectricTestRunner::class) class VectorUnifiedPushMessagingReceiverTest { @@ -106,13 +105,13 @@ class VectorUnifiedPushMessagingReceiverTest { fun `pushHandler returning true locks the wake lock but does not unlock it so it continues to run`() = runTest { val context = InstrumentationRegistry.getInstrumentation().context val pushHandlerResult = lambdaRecorder { _, _ -> true } - val lockLambda = lambdaRecorder { _ -> } - val unlockLambda = lambdaRecorder { } + val lockLambda = lambdaRecorder { true } + val unlockLambda = lambdaRecorder { true } val vectorUnifiedPushMessagingReceiver = createVectorUnifiedPushMessagingReceiver( pushHandler = FakePushHandler( handleResult = pushHandlerResult ), - pushHandlingWakeLock = FakePushHandlingWakeLock( + pushHandlingWakeLock = FakeFetchPushForegroundServiceManager( lock = lockLambda, unlock = unlockLambda, ), @@ -133,13 +132,13 @@ class VectorUnifiedPushMessagingReceiverTest { fun `pushHandler returning false locks and unlocks the wakelock early`() = runTest { val context = InstrumentationRegistry.getInstrumentation().context val pushHandlerResult = lambdaRecorder { _, _ -> false } - val lockLambda = lambdaRecorder { _ -> } - val unlockLambda = lambdaRecorder { } + val lockLambda = lambdaRecorder { true } + val unlockLambda = lambdaRecorder { true } val vectorUnifiedPushMessagingReceiver = createVectorUnifiedPushMessagingReceiver( pushHandler = FakePushHandler( handleResult = pushHandlerResult ), - pushHandlingWakeLock = FakePushHandlingWakeLock( + pushHandlingWakeLock = FakeFetchPushForegroundServiceManager( lock = lockLambda, unlock = unlockLambda, ), @@ -264,7 +263,7 @@ class VectorUnifiedPushMessagingReceiverTest { unifiedPushNewGatewayHandler: UnifiedPushNewGatewayHandler = FakeUnifiedPushNewGatewayHandler(), endpointRegistrationHandler: EndpointRegistrationHandler = EndpointRegistrationHandler(), removedGatewayHandler: UnifiedPushRemovedGatewayHandler = UnifiedPushRemovedGatewayHandler { lambdaError() }, - pushHandlingWakeLock: FakePushHandlingWakeLock = FakePushHandlingWakeLock(), + pushHandlingWakeLock: FakeFetchPushForegroundServiceManager = FakeFetchPushForegroundServiceManager(), ): VectorUnifiedPushMessagingReceiver { return VectorUnifiedPushMessagingReceiver().apply { this.pushParser = unifiedPushParser @@ -277,7 +276,7 @@ class VectorUnifiedPushMessagingReceiverTest { this.removedGatewayHandler = removedGatewayHandler this.endpointRegistrationHandler = endpointRegistrationHandler this.coroutineScope = this@createVectorUnifiedPushMessagingReceiver - this.pushHandlingWakeLock = pushHandlingWakeLock + this.fetchPushForegroundServiceManager = pushHandlingWakeLock } } } From e1b717183976c19ecbe2bace86f15ab4d9d5ef1a Mon Sep 17 00:00:00 2001 From: ElementBot <110224175+ElementBot@users.noreply.github.com> Date: Mon, 20 Apr 2026 19:09:10 +0200 Subject: [PATCH 43/44] Sync Strings (#6626) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Sync Strings from Localazy * Use the previous plurals as plain strings * Add extra case for 1 vs multiple users * Update screenshots --------- Co-authored-by: Jorge Martín --- .../src/main/res/values-bg/translations.xml | 4 - .../src/main/res/values-cs/translations.xml | 11 - .../src/main/res/values-da/translations.xml | 11 - .../src/main/res/values-de/translations.xml | 11 - .../src/main/res/values-el/translations.xml | 11 - .../src/main/res/values-et/translations.xml | 11 - .../src/main/res/values-fa/translations.xml | 11 - .../src/main/res/values-fi/translations.xml | 11 - .../src/main/res/values-fr/translations.xml | 11 - .../src/main/res/values-hr/translations.xml | 11 - .../src/main/res/values-hu/translations.xml | 11 - .../src/main/res/values-it/translations.xml | 11 - .../src/main/res/values-ja/translations.xml | 11 - .../src/main/res/values-ko/translations.xml | 11 - .../src/main/res/values-nb/translations.xml | 11 - .../src/main/res/values-pl/translations.xml | 11 - .../main/res/values-pt-rBR/translations.xml | 11 - .../src/main/res/values-pt/translations.xml | 11 - .../src/main/res/values-ro/translations.xml | 11 - .../src/main/res/values-ru/translations.xml | 11 - .../src/main/res/values-sk/translations.xml | 11 - .../src/main/res/values-tr/translations.xml | 11 - .../src/main/res/values-uk/translations.xml | 7 - .../src/main/res/values-uz/translations.xml | 11 - .../main/res/values-zh-rTW/translations.xml | 11 - .../src/main/res/values-zh/translations.xml | 11 - .../impl/src/main/res/values/localazy.xml | 11 - .../src/main/res/values-de/translations.xml | 4 + .../src/main/res/values-hr/translations.xml | 27 +- .../src/main/res/values-uz/translations.xml | 28 +- .../src/main/res/values-vi/translations.xml | 4 + .../main/res/values-zh-rTW/translations.xml | 32 +- .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 4 +- .../src/main/res/values-uz/translations.xml | 4 +- .../src/main/res/values-vi/translations.xml | 5 + .../main/res/values-zh-rTW/translations.xml | 4 +- .../src/main/res/values-de/translations.xml | 6 +- .../src/main/res/values-hr/translations.xml | 7 +- .../src/main/res/values-ja/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 5 +- .../src/main/res/values-vi/translations.xml | 2 + .../main/res/values-zh-rTW/translations.xml | 7 +- .../src/main/res/values-zh/translations.xml | 2 +- .../invitepeople/impl/InvitePeopleView.kt | 13 +- .../src/main/res/values-ja/translations.xml | 6 - .../impl/src/main/res/values/localazy.xml | 12 +- .../src/main/res/values-vi/translations.xml | 2 + .../src/main/res/values-vi/translations.xml | 3 + .../src/main/res/values-vi/translations.xml | 3 + .../src/main/res/values-uz/translations.xml | 3 + .../main/res/values-zh-rTW/translations.xml | 19 + .../src/main/res/values-de/translations.xml | 4 + .../src/main/res/values-fi/translations.xml | 1 + .../src/main/res/values-hr/translations.xml | 5 + .../src/main/res/values-uz/translations.xml | 5 + .../main/res/values-zh-rTW/translations.xml | 5 + .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 4 +- .../src/main/res/values-vi/translations.xml | 1 + .../main/res/values-zh-rTW/translations.xml | 4 +- .../src/main/res/values-zh/translations.xml | 2 +- .../src/main/res/values-cs/translations.xml | 1 + .../src/main/res/values-da/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 7 +- .../src/main/res/values-el/translations.xml | 1 + .../src/main/res/values-et/translations.xml | 3 + .../src/main/res/values-fi/translations.xml | 9 + .../src/main/res/values-fr/translations.xml | 9 + .../src/main/res/values-hr/translations.xml | 9 + .../src/main/res/values-hu/translations.xml | 9 + .../src/main/res/values-it/translations.xml | 8 + .../src/main/res/values-ja/translations.xml | 9 + .../src/main/res/values-ko/translations.xml | 8 + .../src/main/res/values-lt/translations.xml | 1 + .../src/main/res/values-nb/translations.xml | 1 + .../src/main/res/values-ru/translations.xml | 9 + .../src/main/res/values-uz/translations.xml | 11 + .../src/main/res/values-vi/translations.xml | 7 + .../main/res/values-zh-rTW/translations.xml | 11 + .../src/main/res/values-zh/translations.xml | 4 + .../impl/src/main/res/values/localazy.xml | 3 +- .../src/main/res/values-de/translations.xml | 16 +- .../src/main/res/values-et/translations.xml | 6 +- .../src/main/res/values-hr/translations.xml | 23 +- .../src/main/res/values-uz/translations.xml | 19 +- .../main/res/values-zh-rTW/translations.xml | 25 +- .../src/main/res/values-de/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 7 + .../main/res/values-zh-rTW/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 3 + .../src/main/res/values-vi/translations.xml | 1 + .../src/main/res/values-vi/translations.xml | 5 + .../src/main/res/values-vi/translations.xml | 3 + .../src/main/res/values-uz/translations.xml | 2 +- .../src/main/res/values-vi/translations.xml | 6 + .../main/res/values-zh-rTW/translations.xml | 6 + .../src/main/res/values-de/translations.xml | 4 + .../src/main/res/values-hr/translations.xml | 8 +- .../src/main/res/values-uz/translations.xml | 14 +- .../src/main/res/values-vi/translations.xml | 7 + .../main/res/values-zh-rTW/translations.xml | 25 +- .../src/main/res/values-de/translations.xml | 12 +- .../src/main/res/values-hr/translations.xml | 19 +- .../src/main/res/values-ru/translations.xml | 2 +- .../src/main/res/values-uz/translations.xml | 21 +- .../src/main/res/values-vi/translations.xml | 18 + .../main/res/values-zh-rTW/translations.xml | 25 +- .../src/main/res/values-de/translations.xml | 1 + .../src/main/res/values-hr/translations.xml | 5 +- .../src/main/res/values-uz/translations.xml | 9 +- .../main/res/values-zh-rTW/translations.xml | 20 +- .../src/main/res/values-de/translations.xml | 2 + .../src/main/res/values-hr/translations.xml | 10 + .../src/main/res/values-uz/translations.xml | 10 + .../src/main/res/values-vi/translations.xml | 7 + .../main/res/values-zh-rTW/translations.xml | 9 + .../src/main/res/values-de/translations.xml | 4 +- .../src/main/res/values-et/translations.xml | 2 +- .../src/main/res/values-hr/translations.xml | 6 +- .../src/main/res/values-uz/translations.xml | 6 +- .../src/main/res/values-vi/translations.xml | 5 + .../main/res/values-zh-rTW/translations.xml | 10 +- .../src/main/res/values-et/translations.xml | 1 + .../src/main/res/values-fi/translations.xml | 2 + .../src/main/res/values-fr/translations.xml | 2 + .../src/main/res/values-hr/translations.xml | 2 + .../src/main/res/values-hu/translations.xml | 2 + .../src/main/res/values-ru/translations.xml | 2 + .../src/main/res/values-uz/translations.xml | 2 + .../main/res/values-zh-rTW/translations.xml | 2 + .../src/main/res/values-zh/translations.xml | 1 + .../src/main/res/values-de/translations.xml | 5 + .../src/main/res/values-hr/translations.xml | 5 + .../src/main/res/values-uz/translations.xml | 5 + .../src/main/res/values-vi/translations.xml | 14 + .../main/res/values-zh-rTW/translations.xml | 6 + .../src/main/res/values-vi/translations.xml | 6 + .../src/main/res/values-vi/translations.xml | 7 + .../src/main/res/values-cs/translations.xml | 1 - .../src/main/res/values-da/translations.xml | 1 - .../src/main/res/values-de/translations.xml | 42 +- .../src/main/res/values-el/translations.xml | 1 - .../src/main/res/values-et/translations.xml | 16 +- .../src/main/res/values-fi/translations.xml | 16 +- .../src/main/res/values-fr/translations.xml | 17 +- .../src/main/res/values-hr/translations.xml | 51 +- .../src/main/res/values-hu/translations.xml | 17 +- .../src/main/res/values-it/translations.xml | 8 - .../src/main/res/values-ja/translations.xml | 17 +- .../src/main/res/values-ko/translations.xml | 8 - .../src/main/res/values-lt/translations.xml | 1 - .../src/main/res/values-nb/translations.xml | 1 - .../src/main/res/values-ru/translations.xml | 16 +- .../src/main/res/values-uz/translations.xml | 68 +- .../src/main/res/values-vi/translations.xml | 50 +- .../main/res/values-zh-rTW/translations.xml | 79 +- .../src/main/res/values-zh/translations.xml | 15 +- .../src/main/res/values/localazy.xml | 18 +- screenshots/html/data.js | 2080 +++++++++-------- ...people.impl_InvitePeopleView_Day_10_en.png | 4 +- ...ople.impl_InvitePeopleView_Night_10_en.png | 4 +- ...eybackup_MissingKeyBackupView_Day_0_en.png | 4 +- ...backup_MissingKeyBackupView_Night_0_en.png | 4 +- ...impl.root_PreferencesRootViewDark_0_en.png | 4 +- ...impl.root_PreferencesRootViewDark_1_en.png | 4 +- ...impl.root_PreferencesRootViewDark_2_en.png | 4 +- ...mpl.root_PreferencesRootViewLight_0_en.png | 4 +- ...mpl.root_PreferencesRootViewLight_1_en.png | 4 +- ...mpl.root_PreferencesRootViewLight_2_en.png | 4 +- 174 files changed, 2058 insertions(+), 1617 deletions(-) delete mode 100644 features/announcement/impl/src/main/res/values-bg/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-cs/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-da/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-de/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-el/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-et/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-fa/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-fi/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-fr/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-hr/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-hu/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-it/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-ja/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-ko/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-nb/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-pl/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-pt-rBR/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-pt/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-ro/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-ru/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-sk/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-tr/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-uk/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-uz/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-zh-rTW/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values-zh/translations.xml delete mode 100644 features/announcement/impl/src/main/res/values/localazy.xml create mode 100644 features/location/impl/src/main/res/values-de/translations.xml create mode 100644 features/location/impl/src/main/res/values-hr/translations.xml create mode 100644 features/location/impl/src/main/res/values-uz/translations.xml create mode 100644 features/location/impl/src/main/res/values-zh-rTW/translations.xml create mode 100644 libraries/pushproviders/unifiedpush/src/main/res/values-vi/translations.xml diff --git a/features/announcement/impl/src/main/res/values-bg/translations.xml b/features/announcement/impl/src/main/res/values-bg/translations.xml deleted file mode 100644 index 853cf5f027..0000000000 --- a/features/announcement/impl/src/main/res/values-bg/translations.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - "Присъединете се към обществени пространства" - diff --git a/features/announcement/impl/src/main/res/values-cs/translations.xml b/features/announcement/impl/src/main/res/values-cs/translations.xml deleted file mode 100644 index cf7ead1962..0000000000 --- a/features/announcement/impl/src/main/res/values-cs/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Zobrazit prostory, které jste vytvořili nebo ke kterým jste se připojili" - "Přijmout nebo odmítnout pozvánky do prostorů" - "Objevte všechny místnosti, do kterých můžete vstoupit ve svých prostorech" - "Připojit se k veřejným prostorům" - "Opustit všechny prostory, ke kterým jste se připojili" - "Filtrování, vytváření a správa prostorů bude brzy k dispozici." - "Vítejte v beta verzi prostorů! S touto první verzí můžete:" - "Představujeme prostory" - diff --git a/features/announcement/impl/src/main/res/values-da/translations.xml b/features/announcement/impl/src/main/res/values-da/translations.xml deleted file mode 100644 index 76540962e1..0000000000 --- a/features/announcement/impl/src/main/res/values-da/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Se klynger, du har oprettet eller tilmeldt dig" - "Acceptere eller afvise invitationer til klynger" - "Finde alle rum, du kan deltage i, i dine klynger" - "Deltage i offentlige klynger" - "Forlade de klynger, du har tilsluttet dig" - "Filtrering, oprettelse og administration af klynger kommer snart." - "Velkommen til betaversionen af Klynger! Med denne første version kan du:" - "Introduktion til Klynger" - diff --git a/features/announcement/impl/src/main/res/values-de/translations.xml b/features/announcement/impl/src/main/res/values-de/translations.xml deleted file mode 100644 index 11f5f3a99c..0000000000 --- a/features/announcement/impl/src/main/res/values-de/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Von dir erstellte oder beigetretene Spaces anzeigen" - "Einladungen zu Spaces annehmen oder ablehnen" - "Chats innerhalb deiner Spaces entdecken, um ihnen beizutreten" - "Öffentlichen Spaces beitreten" - "Spaces verlassen, bei denen du Mitglied bist" - "Das Filtern, Erstellen und Verwalten von Spaces ist bald verfügbar." - "Willkommen bei der Beta-Version von Spaces! Mit dieser ersten Version kannst du:" - "Einführung in Spaces" - diff --git a/features/announcement/impl/src/main/res/values-el/translations.xml b/features/announcement/impl/src/main/res/values-el/translations.xml deleted file mode 100644 index bdeb821efb..0000000000 --- a/features/announcement/impl/src/main/res/values-el/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Δείτε τους χώρους που έχετε δημιουργήσει ή στους οποίους έχετε εγγραφεί" - "Να αποδεχθείτε ή να απορρίψετε προσκλήσεις σε χώρους" - "Να ανακαλύψτε όλες τις αίθουσες που μπορείτε να συμμετάσχετε στους χώρους σας" - "Να συμμετάσχετε σε δημόσιους χώρους" - "Να αποχωρήστε από χώρους στους οποίους έχετε συμμετάσχει" - "Το φιλτράρισμα, η δημιουργία και η διαχείριση χώρων θα είναι σύντομα διαθέσιμα." - "Καλώς ορίσατε στην δοκιμαστική έκδοση των Χώρων! Με αυτήν την πρώτη έκδοση μπορείτε:" - "Παρουσιάζοντας τους Χώρους" - diff --git a/features/announcement/impl/src/main/res/values-et/translations.xml b/features/announcement/impl/src/main/res/values-et/translations.xml deleted file mode 100644 index ee2ba9c3b4..0000000000 --- a/features/announcement/impl/src/main/res/values-et/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Vaadata kogukondi, mille oled loonud või millega oled liitunud" - "Nõustuda kutsetega liitumiseks kogukonnaga või sellest keelduda" - "Uurida neis kogukondades leiduvaid jututube ning nendega liituda" - "Liituda avalike kogukondadega" - "Lahkuda kogukonnast, millega oled liitunud" - "Kogukondade filtreerimine, loomine ja haldamine lisandub peagi" - "Tere tulemast kasutama kogukondade beetaversiooni! Selles esimeses versioonis saad sa:" - "Võtame kasutusele kogukonnad" - diff --git a/features/announcement/impl/src/main/res/values-fa/translations.xml b/features/announcement/impl/src/main/res/values-fa/translations.xml deleted file mode 100644 index 2e8902ae23..0000000000 --- a/features/announcement/impl/src/main/res/values-fa/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "دیدن فضاهایی که ساخته یا پیوسته‌اید" - "پذیرش یا رد دعوت‌ها به فضاها" - "کشف تمامی اتاق‌هایی که می‌توانید در فضاهایتان بپیوندید" - "پیوستن به فضاهای عمومی" - "ترک هر فضایی که پیوسته‌اید" - "پالایش، ایجاد و مدیریت کردن فضاها به زودی." - "به نگارش آزمایشی فضاها خوش آمدید! در این نگارش می‌توانید:" - "معرّفی فضاها" - diff --git a/features/announcement/impl/src/main/res/values-fi/translations.xml b/features/announcement/impl/src/main/res/values-fi/translations.xml deleted file mode 100644 index 8e7674487f..0000000000 --- a/features/announcement/impl/src/main/res/values-fi/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Nähdä luomasi tai liittymäsi tilat" - "Hyväksyä tai hylätä kutsuja tiloihin" - "Löytää kaikki huoneet, joihin voit liittyä tiloissasi" - "Liittyä julkisiin tiloihin" - "Poistua mistä tahansa tilasta, johon olet liittynyt" - "Tilojen suodatus, luominen ja hallinta on tulossa pian." - "Tervetuloa tilojen beetaversioon! Tämän ensimmäisen version avulla voit:" - "Esittelyssä tilat" - diff --git a/features/announcement/impl/src/main/res/values-fr/translations.xml b/features/announcement/impl/src/main/res/values-fr/translations.xml deleted file mode 100644 index 7e042c65ff..0000000000 --- a/features/announcement/impl/src/main/res/values-fr/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Voir les espaces que vous avez créés ou rejoints" - "Accepter ou refuser les invitations aux espaces" - "Découvrir les salons que vous pouvez joindre depuis vos espaces" - "Rejoindre les espaces publics" - "Quitter les espaces dont vous êtes membre." - "Le filtrage, la création et la gestion des espaces seront bientôt disponibles." - "Bienvenue dans la version bêta des espaces! Avec cette première version, vous pourrez :" - "Ajout des espaces" - diff --git a/features/announcement/impl/src/main/res/values-hr/translations.xml b/features/announcement/impl/src/main/res/values-hr/translations.xml deleted file mode 100644 index e78f29f19a..0000000000 --- a/features/announcement/impl/src/main/res/values-hr/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Pregledajte prostore koje ste stvorili ili kojima ste se pridružili" - "Prihvatite ili odbijte pozivnice za prostore" - "Otkrijte sve sobe kojima se možete pridružiti u svojim prostorima" - "Pridružite se javnim prostorima" - "Napustite sve prostore kojima ste se pridružili" - "Uskoro stiže filtriranje i stvaranje prostora te upravljanje njima." - "Dobrodošli u beta inačicu prostora! S ovom prvom inačicom možete:" - "Predstavljamo prostore" - diff --git a/features/announcement/impl/src/main/res/values-hu/translations.xml b/features/announcement/impl/src/main/res/values-hu/translations.xml deleted file mode 100644 index b09f70419b..0000000000 --- a/features/announcement/impl/src/main/res/values-hu/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Az Ön által létrehozott vagy csatlakozott térek megtekintése" - "A meghívások elfogadására vagy elutasítására a terekhez" - "Szobák felfedezése a terekben, amelyekhez csatlakozhat" - "Csatlakozás nyilvános terekhez" - "Terek elhagyása" - "Terek szűrése, készítése és kezelése hamarosan érkezik." - "Üdvözöljük a tér béta verziójában! Ezzel az első verzióval a következőket teheti:" - "Bemutatkoznak a terek" - diff --git a/features/announcement/impl/src/main/res/values-it/translations.xml b/features/announcement/impl/src/main/res/values-it/translations.xml deleted file mode 100644 index 584ddcdf21..0000000000 --- a/features/announcement/impl/src/main/res/values-it/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Visualizza gli spazi che hai creato o a cui partecipi" - "Accetta o rifiuta gli inviti agli spazi" - "Scopri tutte le stanze a cui puoi partecipare nei tuoi spazi" - "Unisciti agli spazi pubblici" - "Lascia tutti gli spazi a cui ti sei unito" - "A breve saranno disponibili le funzionalità di filtraggio, creazione e gestione degli spazi." - "Benvenuti alla versione beta degli Spazi! Con questa prima versione potrete:" - "Ti presentiamo gli Spazi" - diff --git a/features/announcement/impl/src/main/res/values-ja/translations.xml b/features/announcement/impl/src/main/res/values-ja/translations.xml deleted file mode 100644 index 47273cc12d..0000000000 --- a/features/announcement/impl/src/main/res/values-ja/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "作成または参加したスペースを表示できます" - "スペースへの招待を受諾または拒否できます" - "スペース内の参加可能なルームを検索できます" - "公開スペースに参加できます" - "参加したスペースを退出できます" - "スペースの作成や管理, フィルター検索は近日実装予定です。" - "ベータ版のスペースにようこそ。この最新のバージョンでは:" - "スペースの紹介" - diff --git a/features/announcement/impl/src/main/res/values-ko/translations.xml b/features/announcement/impl/src/main/res/values-ko/translations.xml deleted file mode 100644 index 3fbf2b953c..0000000000 --- a/features/announcement/impl/src/main/res/values-ko/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "직접 만들거나 참여 중인 스페이스 보기" - "스페이스 초대 수락 또는 거절" - "참여 가능한 스페이스 내 모든 방 탐색" - "공개 스페이스 참여" - "참여 중인 스페이스 나가기" - "스페이스 필터링, 생성 및 관리 기능이 곧 추가될 예정입니다." - "스페이스 베타 버전에 오신 것을 환영합니다! 이번 첫 번째 버전에서는 다음과 같은 기능을 이용하실 수 있습니다.:" - "스페이스 소개" - diff --git a/features/announcement/impl/src/main/res/values-nb/translations.xml b/features/announcement/impl/src/main/res/values-nb/translations.xml deleted file mode 100644 index 553ff9f997..0000000000 --- a/features/announcement/impl/src/main/res/values-nb/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Se områder du har opprettet eller blitt med i" - "Godta eller avslå invitasjoner til områder" - "Oppdag alle rom du kan bli med i i dine områder" - "Bli med i offentlige områder" - "Forlat områder du har blitt med i" - "Oppretting, filtrering og administrasjon av områder kommer snart." - "Velkommen til betaversjonen av Områder! Med denne første versjonen kan du:" - "Vi introduserer Områder" - diff --git a/features/announcement/impl/src/main/res/values-pl/translations.xml b/features/announcement/impl/src/main/res/values-pl/translations.xml deleted file mode 100644 index 4308bdd81d..0000000000 --- a/features/announcement/impl/src/main/res/values-pl/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Wyświetlić przestrzenie, które stworzyłeś lub do których dołączyłeś" - "Akceptować lub odrzucać zaproszenia" - "Odkrywać wszystkie pokoje, do których możesz dołączyć w swoich przestrzeniach" - "Dołączać do przestrzeni publicznych" - "Opuszczać jakąkolwiek przestrzeń, do której dołączyłeś" - "Filtrowanie, tworzenie i zarządzanie przestrzeniami pojawi się wkrótce." - "Witamy w wersji beta przestrzeni! W tej wersji możesz:" - "Przedstawiamy przestrzenie" - diff --git a/features/announcement/impl/src/main/res/values-pt-rBR/translations.xml b/features/announcement/impl/src/main/res/values-pt-rBR/translations.xml deleted file mode 100644 index 32a9bf85af..0000000000 --- a/features/announcement/impl/src/main/res/values-pt-rBR/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Visualizar espaços que criou ou entrou" - "Aceitar ou recusar convites aos espaços" - "Descobrir quaisquer salas que você pode entrar nos espaços" - "Entrar espaços públicos" - "Sair de quaisquer espaços que entrou" - "Filtrar, criar, e gerenciar espaços virão em breve." - "Boas-vindas à versão beta dos Espaços! Com essa primeira versão, você pode:" - "Apresentando Espaços" - diff --git a/features/announcement/impl/src/main/res/values-pt/translations.xml b/features/announcement/impl/src/main/res/values-pt/translations.xml deleted file mode 100644 index 744ac74bd3..0000000000 --- a/features/announcement/impl/src/main/res/values-pt/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Ver espaços que criaste ou nos quais entraste" - "Aceitar ou recusar convites para espaços" - "Descobrir todas as salas dos seus espaços nas quais podes entrar" - "Entrar em espaços públicos" - "Deixar todos os espaços em que entraste" - "Em breve, será possível filtrar, criar e gerir espaços." - "Eis a versão beta dos Espaços! Nesta primeira versão, podes:" - "Apresentamos os Espaços" - diff --git a/features/announcement/impl/src/main/res/values-ro/translations.xml b/features/announcement/impl/src/main/res/values-ro/translations.xml deleted file mode 100644 index 716f1faeb2..0000000000 --- a/features/announcement/impl/src/main/res/values-ro/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Vizualizați spațiile pe care le-ați creat sau la care v-ați alăturat" - "Acceptați sau refuzați invitațiile la spații" - "Descoperiți toate camerele la care vă puteți alătura în spațiile dumneavoastră." - "Alăturați-vă spațiilor publice" - "Părăsiți spațiile la care v-ați alăturat." - "Filtrarea, crearea și gestionarea spațiilor vor fi disponibile în curând." - "Bun venit la versiunea beta a Spațiilor! Cu această primă versiune puteți:" - "Vă prezentăm Spații" - diff --git a/features/announcement/impl/src/main/res/values-ru/translations.xml b/features/announcement/impl/src/main/res/values-ru/translations.xml deleted file mode 100644 index 46d005c8cd..0000000000 --- a/features/announcement/impl/src/main/res/values-ru/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Просматривать пространства, которые вы создали или к которым присоединились" - "Принимать или отклонять приглашения в пространства" - "Находить все комнаты, к которым можно присоединиться в ваших пространствах" - "Присоединяться к публичным пространствам" - "Покидать все пространства, к которым вы присоединились" - "Фильтровать, создавать пространства и управлять ими можно будет позже." - "Добро пожаловать в бета-версию пространств! Сейчас вы сможете:" - "Представляем пространства" - diff --git a/features/announcement/impl/src/main/res/values-sk/translations.xml b/features/announcement/impl/src/main/res/values-sk/translations.xml deleted file mode 100644 index 0b305499a7..0000000000 --- a/features/announcement/impl/src/main/res/values-sk/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Zobraziť priestory, ktoré ste vytvorili alebo ku ktorým ste sa pripojili" - "Prijímať alebo odmietať pozvánky do priestorov" - "Objaviť všetky miestnosti, do ktorých sa môžete pripojiť vo svojich priestoroch" - "Pripojiť sa k verejnému priestoru" - "Opustiť akékoľvek priestory, ku ktorým ste sa pridali" - "Filtrovanie, vytváranie a správa priestorov bude čoskoro k dispozícii." - "Vitajte v beta verzii priestorov! S touto prvou verziou môžete:" - "Predstavujeme priestory" - diff --git a/features/announcement/impl/src/main/res/values-tr/translations.xml b/features/announcement/impl/src/main/res/values-tr/translations.xml deleted file mode 100644 index 8551dbb02b..0000000000 --- a/features/announcement/impl/src/main/res/values-tr/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Oluşturduğunuz veya katıldığınız alanları görüntüleyin" - "Alan davetlerini kabul edin veya reddedin" - "Alanlarınızdaki katılabileceğiniz odaları keşfedin" - "Herkese açık alanlara katılın" - "Katıldığınız alanlardan ayrılın" - "Alanları filtreleme, oluşturma ve yönetme yakında geliyor." - "Alanlar’ın beta sürümüne hoş geldiniz! Bu ilk sürümle şunları yapabilirsiniz:" - "Alanlar ile tanışın" - diff --git a/features/announcement/impl/src/main/res/values-uk/translations.xml b/features/announcement/impl/src/main/res/values-uk/translations.xml deleted file mode 100644 index de3c1b0324..0000000000 --- a/features/announcement/impl/src/main/res/values-uk/translations.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - "Знаходьте у своїх просторах кімнати, до яких можна приєднатися" - "Фільтрування, створення та керування просторами стане доступним найближчим часом." - "Ласкаво просимо до бета-версії Просторів! У цій першій версії ви можете:" - "Представляємо Простори" - diff --git a/features/announcement/impl/src/main/res/values-uz/translations.xml b/features/announcement/impl/src/main/res/values-uz/translations.xml deleted file mode 100644 index 12356160b8..0000000000 --- a/features/announcement/impl/src/main/res/values-uz/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "Siz yaratgan yoki qo‘shilgan maydonlarni ko‘rish" - "Maydonlarga takliflarni qabul qilish yoki rad etish" - "Maydonlaringizga qo‘shilishingiz mumkin bo‘lgan xonalarni kashf eting" - "Jamoat maydonlariga qo‘shilish" - "Kirgan maydonlaringizni tark eting" - "Maydonlarni filtrlash, yaratish va boshqarish tez orada amalga oshiriladi." - "Maydonlar beta versiyasiga xush kelibsiz! Bu birinchi versiya bilan siz:" - "Maydonlar bilan tanishish" - diff --git a/features/announcement/impl/src/main/res/values-zh-rTW/translations.xml b/features/announcement/impl/src/main/res/values-zh-rTW/translations.xml deleted file mode 100644 index a5b82752bc..0000000000 --- a/features/announcement/impl/src/main/res/values-zh-rTW/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "檢視您建立或加入的空間" - "接受或拒絕空間邀請" - "探索空間內您可以加入的任何聊天室" - "加入公開空間" - "離開任何您已加入的空間" - "篩選、建立與管理空間功能即將推出。" - "歡迎使用空間的測試版!此初始版本可讓您:" - "介紹空間" - diff --git a/features/announcement/impl/src/main/res/values-zh/translations.xml b/features/announcement/impl/src/main/res/values-zh/translations.xml deleted file mode 100644 index 70d86638ea..0000000000 --- a/features/announcement/impl/src/main/res/values-zh/translations.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "查看您创建或加入的空间" - "接受或拒绝空间邀请" - "发现您可以加入空间的所有房间" - "加入公共空间" - "离开你加入的所有空间" - "筛选、创建及管理空间功能即将上线。" - "欢迎使用空间测试版!使用首个版本,您可以:" - "空间简介" - diff --git a/features/announcement/impl/src/main/res/values/localazy.xml b/features/announcement/impl/src/main/res/values/localazy.xml deleted file mode 100644 index 5e7b8a6713..0000000000 --- a/features/announcement/impl/src/main/res/values/localazy.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - "View spaces you\'ve created or joined" - "Accept or decline invites to spaces" - "Discover any rooms you can join in your spaces" - "Join public spaces" - "Leave any spaces you’ve joined" - "Filtering, creating and managing spaces is coming soon." - "Welcome to the beta version of Spaces! With this first version you can:" - "Introducing Spaces" - diff --git a/features/createroom/impl/src/main/res/values-de/translations.xml b/features/createroom/impl/src/main/res/values-de/translations.xml index d1f5bfd283..4408bf66a3 100644 --- a/features/createroom/impl/src/main/res/values-de/translations.xml +++ b/features/createroom/impl/src/main/res/values-de/translations.xml @@ -8,15 +8,19 @@ "Neuer Chat" "Neuer Space" "Nur eingeladene Personen haben Zutritt zu diesem Chat." + "Privat" "Jeder kann diesen Chat finden. Du kannst dies jederzeit in den Einstellungen des Chats ändern." "Jeder kann beitreten." + "Öffentlich" "Jeder kann den Beitritt zum Chat erbitten, aber ein Admin oder Moderator muss die Anfrage akzeptieren." "Anfrage zum Beitritt zulassen" "Jeder in %1$s kann beitreten, aber alle anderen müssen den Beitritt anfragen." "Beitritt anfragen" "Nur eingeladene Personen können beitreten." + "Privat" "Jeder darf diesem Chat beitreten." + "Öffentlich" "Jeder in %1$s kann beitreten." "Standard" "Wer hat Zugang" diff --git a/features/createroom/impl/src/main/res/values-hr/translations.xml b/features/createroom/impl/src/main/res/values-hr/translations.xml index 81979e3f84..17336bebf2 100644 --- a/features/createroom/impl/src/main/res/values-hr/translations.xml +++ b/features/createroom/impl/src/main/res/values-hr/translations.xml @@ -3,15 +3,34 @@ "Nova soba" "Pozovi osobe" "Došlo je do pogreške prilikom stvaranja sobe" + "Prostor nije moguće stvoriti zbog nepoznate pogreške. Pokušajte ponovno kasnije." + "Dodaj ime…" "Nova soba" - "Samo pozvane osobe mogu pristupiti ovoj sobi. Sve su poruke sveobuhvatno šifrirane." + "Novi prostor" + "Samo pozvane osobe mogu se pridružiti." + "Privatno" "Svatko može pronaći ovu sobu. To možete u svakom trenutku promijeniti u postavkama sobe." + "Svatko se može pridružiti." + "Javno" "Svatko može zatražiti pridruživanje sobi, ali administrator ili moderator morat će prihvatiti zahtjev." - "Zatraži pridruživanje" - "Svatko se može pridružiti ovoj sobi" + "Dopusti traženje pridruživanja" + "Svatko u %1$s može se pridružiti, ali svi ostali moraju zatražiti pristup." + "Zatraži pridruživanje" + "Samo pozvane osobe mogu pristupiti ovoj sobi. Sve su poruke sveobuhvatno šifrirane." + "Privatno" + "Svatko se može pridružiti." + "Javno" + "Svatko u %1$s može se pridružiti." + "Standard" + "Tko ima pristup" "Da bi ova soba bila vidljiva u javnom direktoriju soba, trebat će vam adresa sobe." - "Adresa sobe" + "Adresa" "Vidljivost sobe" + "(bez razmaka)" + "Ne dodavaj u prostor" + "Nije odabran nijedan prostor" + "Dodaj u prostor" "Tema (neobavezno)" + "Dodaj opis…" diff --git a/features/createroom/impl/src/main/res/values-uz/translations.xml b/features/createroom/impl/src/main/res/values-uz/translations.xml index 98e246716d..88de696f64 100644 --- a/features/createroom/impl/src/main/res/values-uz/translations.xml +++ b/features/createroom/impl/src/main/res/values-uz/translations.xml @@ -3,14 +3,34 @@ "Yangi xona" "Odamlarni taklif qiling" "Xonani yaratishda xatolik yuz berdi" + "Noma’lum xatolik tufayli maydon yaratilmadi. Keyinroq qayta urining." + "Ism qo‘shish…" + "Yangi xona" + "Yangi maydon" "Faqat taklif etilgan shaxslargina bu xonaga kira oladi. Barcha xabarlar boshdan-oxirigacha shifrlanadi." + "Maxfiy" "Bu xonani har kim topishi mumkin. Buni xona sozlamalaridan istalgan vaqtda oʻzgartirishingiz mumkin." - "Xonaga qo‘shilishni istalgan kishi so‘rashi mumkin, lekin administrator yoki moderator so‘rovni qabul qilishi kerak" - "Qo‘shilishni so‘rang" - "Bu xonaga istalgan kishi qo‘shilishi mumkin" - "Ushbu xona ommaviy xonalar ro‘yxatida ko‘rinishi uchun sizga xona manzili kerak bo‘ladi." + "Istalgan kishi qo‘shilishi mumkin" + "Ommaviy" + "Istalgan kishi qo‘shilishni so‘rashi mumkin, lekin administrator yoki moderator so‘rovni qabul qilishi kerak." + "Qo‘shilish uchun ruxsat so‘rash" + "%1$s ichidagi har kim kirishi mumkin, lekin boshqalar ruxsat so‘rashi kerak." + "Qo‘shilish uchun so‘rash" + "Faqat taklif qilinganlar qo‘shilishi mumkin." + "Maxfiy" + "Istalgan kishi qo‘shilishi mumkin" + "Ommaviy" + "%1$s ichidagi har kim qo‘shilishi mumkin." + "Standart" + "Kimning kirish huquqi bor" + "Ommaviy katalogda ko‘rinadigan qilish uchun manzil kerak bo‘ladi." "Xona manzili" "Xonaning ko‘rinishi" + "(maydon yo‘q)" + "Maydonga kiritilmasin" + "Hech qanday maydon tanlanmagan" + "Maydonga qo‘shish" "Mavzu (ixtiyoriy)" + "Tavsif kiritish…" diff --git a/features/createroom/impl/src/main/res/values-vi/translations.xml b/features/createroom/impl/src/main/res/values-vi/translations.xml index b10d15e077..cde672d7de 100644 --- a/features/createroom/impl/src/main/res/values-vi/translations.xml +++ b/features/createroom/impl/src/main/res/values-vi/translations.xml @@ -4,8 +4,12 @@ "Mời ai đó" "Đã xảy ra lỗi khi tạo phòng." "Chỉ những người được mời mới có thể tham gia." + "Riêng tư" "Bất kỳ ai cũng có thể tìm thấy phòng này. Bạn có thể thay đổi cài đặt phòng bất cứ lúc nào." + "Công cộng" + "Riêng tư" + "Công cộng" "Chủ đề (tùy chọn)" "Thêm mô tả…" diff --git a/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml b/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml index 05495a0594..0899f065d7 100644 --- a/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/createroom/impl/src/main/res/values-zh-rTW/translations.xml @@ -3,14 +3,34 @@ "建立聊天室" "邀請夥伴" "建立聊天室時發生錯誤" - "僅被邀請的人才能存取此聊天室。所有訊息均會端到端加密。" + "因為未知錯誤,無法建立空間。請稍後再試。" + "新增名稱……" + "新聊天室" + "新空間" + "僅被邀請的人才能加入。" + "私人" "任何人都可以找到此聊天室。 您隨時都可以在聊天室設定中變更此設定。" - "任何人都可以要求加入聊天室,但管理員或版主必須接受該請求" - "要求加入" - "任何人都可以加入此聊天室" - "為了讓此聊天室在公開聊天室目錄中可見,您需要聊天室地址。" - "聊天室地址" + "任何人都可以加入。" + "公開" + "任何人都可以要求加入,但管理員或版主必須接受該請求" + "允許要求加入" + "任何在 %1$s 中的人都可以加入,但其他人就必須申請存取權。" + "要求加入" + "僅被邀請的人才可以加入。" + "私人" + "任何人都可以加入" + "公開" + "在 %1$s 中的任何人都可以加入。" + "標準" + "誰有權存取" + "您需要地址才能讓該資訊在公開目錄中顯示。" + "地址" "聊天室能見度" + "(沒有空間)" + "不要新增至空間" + "未選取空間" + "新增至空間" "主題(非必填)" + "新增描述……" diff --git a/features/deactivation/impl/src/main/res/values-vi/translations.xml b/features/deactivation/impl/src/main/res/values-vi/translations.xml index 22bc0a6d6e..b61167ff80 100644 --- a/features/deactivation/impl/src/main/res/values-vi/translations.xml +++ b/features/deactivation/impl/src/main/res/values-vi/translations.xml @@ -1,7 +1,14 @@ + "Vui lòng xác nhận rằng bạn muốn vô hiệu hóa tài khoản của mình. Hành động này không thể hoàn tác." "Xóa tất cả tin nhắn của tôi" "Cảnh báo: Người dùng sau này có thể thấy các cuộc trò chuyện chưa hoàn chỉnh." + "Việc vô hiệu hóa tài khoản của bạn là %1$s , nó sẽ:" + "không thể đảo ngược" + "%1$s Tài khoản của bạn (bạn không thể đăng nhập lại và ID của bạn không thể được sử dụng lại)." + "Vô hiệu hóa vĩnh viễn" + "Loại bỏ bạn khỏi tất cả các phòng chat." + "Xóa thông tin tài khoản của bạn khỏi máy chủ nhận dạng của chúng tôi." "Tin nhắn của bạn vẫn sẽ hiển thị cho người dùng đã đăng ký nhưng sẽ không hiển thị cho người dùng mới hoặc chưa đăng ký nếu bạn chọn xóa chúng." "Vô hiệu hóa tài khoản" diff --git a/features/ftue/impl/src/main/res/values-de/translations.xml b/features/ftue/impl/src/main/res/values-de/translations.xml index 474d085df0..241f73516e 100644 --- a/features/ftue/impl/src/main/res/values-de/translations.xml +++ b/features/ftue/impl/src/main/res/values-de/translations.xml @@ -2,7 +2,7 @@ "Bestätigung unmöglich?" "Erstelle einen neuen Wiederherstellungsschlüssel" - "Verifiziere dieses Gerät, um sichere Chats einzurichten." + "Wähle eine Verifizierungsmethode, um den sicheren Nachrichtenversand einzurichten." "Bestätige deine Identität" "Ein anderes Gerät verwenden" "Wiederherstellungsschlüssel verwenden" diff --git a/features/ftue/impl/src/main/res/values-et/translations.xml b/features/ftue/impl/src/main/res/values-et/translations.xml index 4790fdb716..3e961d6249 100644 --- a/features/ftue/impl/src/main/res/values-et/translations.xml +++ b/features/ftue/impl/src/main/res/values-et/translations.xml @@ -3,7 +3,7 @@ "Kas kinnitamine pole võimalik?" "Loo uus taastevõti" "Krüptitud sõnumivahetuse tagamiseks verifitseeri see seade." - "Kinnita, et see oled sina" + "Kinnita oma digitaalne identiteet" "Kasuta teist seadet" "Kasuta taastevõtit" "Nüüd saad saata või lugeda sõnumeid turvaliselt ning kõik sinu vestluspartnerid võivad usaldada seda seadet." diff --git a/features/ftue/impl/src/main/res/values-hr/translations.xml b/features/ftue/impl/src/main/res/values-hr/translations.xml index d535c660a2..f5aeb642b1 100644 --- a/features/ftue/impl/src/main/res/values-hr/translations.xml +++ b/features/ftue/impl/src/main/res/values-hr/translations.xml @@ -2,8 +2,8 @@ "Ne možete potvrditi?" "Izradi novi ključ za oporavak" - "Potvrdite ovaj uređaj kako biste postavili sigurnu razmjenu poruka." - "Potvrdite svoj identitet" + "Odaberite način potvrde za postavljanje sigurne razmjene poruka." + "Potvrdite svoj digitalni identitet" "Upotrijebite drugi uređaj" "Upotrijebi ključ za oporavak" "Sada možete sigurno čitati ili slati poruke, a svatko s kim razgovarate također može vjerovati ovom uređaju." diff --git a/features/ftue/impl/src/main/res/values-uz/translations.xml b/features/ftue/impl/src/main/res/values-uz/translations.xml index 8edff2c305..2279bb6c92 100644 --- a/features/ftue/impl/src/main/res/values-uz/translations.xml +++ b/features/ftue/impl/src/main/res/values-uz/translations.xml @@ -2,8 +2,8 @@ "Tasdiqlay olmayapsizmi?" "Yangi tiklash kalitini yarating" - "Xavfsiz xabarlashuvni sozlash uchun ushbu qurilmani tasdiqlang." - "Shaxsingizni tasdiqlang" + "Xavfsiz xabar almashinuvni sozlash uchun tasdiqlash usulini tanlang." + "Raqamli shaxsingizni tasdiqlang" "Boshqa qurilmadan foydalanish" "Qayta tiklash kalitidan foydalaning" "Endi xabarlarni xavfsiz tarzda o‘qish yoki yuborish imkoniyatiga egasiz, shuningdek, siz bilan muloqot qilayotgan har qanday kishi ham bu qurilmaga ishonch bildirishi mumkin." diff --git a/features/ftue/impl/src/main/res/values-vi/translations.xml b/features/ftue/impl/src/main/res/values-vi/translations.xml index c70d9be0fb..6ea7d8bf91 100644 --- a/features/ftue/impl/src/main/res/values-vi/translations.xml +++ b/features/ftue/impl/src/main/res/values-vi/translations.xml @@ -1,9 +1,14 @@ + "Không thể xác nhận?" + "Tạo khóa khôi phục mới" "Chọn phương thức xác minh để bật nhắn tin bảo mật." "Xác nhận danh tính kỹ thuật số của bạn" + "Dùng thiết bị khác" + "Sử dụng khóa khôi phục" "Giờ đây bạn có thể đọc và gửi tin nhắn một cách an toàn, và những người bạn trò chuyện cũng có thể tin tưởng thiết bị này." "Thiết bị được xác thực" + "Dùng thiết bị khác" "Đang chờ trên thiết bị khác…" "Bạn có thể thay đổi cài đặt sau." "Cho phép thông báo để không bỏ lỡ bất kỳ tin nhắn nào" diff --git a/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml b/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml index 6340efdbc3..9bad2d1705 100644 --- a/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/ftue/impl/src/main/res/values-zh-rTW/translations.xml @@ -2,8 +2,8 @@ "無法確認?" "建立新的復原金鑰" - "驗證這部裝置以設定安全通訊。" - "確認這是你本人" + "選擇驗證方式以設定安全訊息傳遞。" + "確認您的數位身份" "使用另一部裝置" "使用復原金鑰" "您可以安全地讀取和發送訊息了,與您聊天的人也可以信任這部裝置。" diff --git a/features/home/impl/src/main/res/values-de/translations.xml b/features/home/impl/src/main/res/values-de/translations.xml index f504d5c8e1..ee6cef29de 100644 --- a/features/home/impl/src/main/res/values-de/translations.xml +++ b/features/home/impl/src/main/res/values-de/translations.xml @@ -5,9 +5,9 @@ "Kommen die Benachrichtigungen nicht an?" "Dein Benachrichtigungs-Ping wurde aktualisiert – klarer, schneller und weniger störend." "Wir haben deine Sounds aktualisiert" - "Stelle Deine kryptographische Identität und Deinen Nachrichtenverlauf mit Hilfe eines Wiederherstellungsschlüssels wieder her, falls du alle deine Geräte verloren haben solltest" - "Wiederherstellung einrichten" - "Wiederherstellung einrichten" + "Deine Chats werden automatisch gesichert und mit einer Ende-zu-Ende-Verschlüsselung geschützt. Um dieses Backup wiederherzustellen und deine digitale Identität zu bewahren, falls du den Zugriff auf alle deine Geräte verlierst, benötigst du deinen Wiederherstellungsschlüssel." + "Wiederherstellungsschlüssel einrichten" + "Sichere deine Chats" "Bestätige deinen Wiederherstellungsschlüssel, um weiterhin auf deinen Schlüsselspeicher und den Nachrichtenverlauf zugreifen zu können." "Gib deinen Wiederherstellungsschlüssel ein" "Hast du deinen Wiederherstellungsschlüssel vergessen?" diff --git a/features/home/impl/src/main/res/values-hr/translations.xml b/features/home/impl/src/main/res/values-hr/translations.xml index 233cac78d8..eae429a0e5 100644 --- a/features/home/impl/src/main/res/values-hr/translations.xml +++ b/features/home/impl/src/main/res/values-hr/translations.xml @@ -5,9 +5,9 @@ "Obavijesti ne stižu?" "Vaš je signal obavijesti ažuriran – jasniji je, brži i manje ometajući." "Ažurirali smo vaše zvukove" - "Ako ste izgubili sve postojeće uređaje, oporavite svoj kriptografski identitet i povijest poruka pomoću ključa za oporavak." - "Postavljanje oporavka" - "Postavite oporavak kako biste zaštitili svoj račun" + "Vaši se razgovori automatski sigurnosno kopiraju enkripcijom od početka do kraja. Da biste vratili ovu sigurnosnu kopiju i zadržali svoj digitalni identitet kada izgubite pristup svim svojim uređajima, trebat će vam ključ za oporavak." + "ključ za oporavak" + "Napravite sigurnosnu kopiju svojih razgovora" "Potvrdite svoj ključ za oporavak kako biste zadržali pristup pohrani ključeva i povijesti poruka." "Unesite svoj ključ za oporavak" "Zaboravili ste ključ za oporavak?" @@ -50,6 +50,7 @@ Nemate nepročitanih poruka!" "Označi kao pročitano" "Označi kao nepročitano" "Ova je soba nadograđena" + "Vaši prostori" "Izgleda da koristite novi uređaj. Izvršite provjeru drugim uređajem da biste pristupili svojim šifriranim porukama." "Potvrdi identitet" diff --git a/features/home/impl/src/main/res/values-ja/translations.xml b/features/home/impl/src/main/res/values-ja/translations.xml index 3e4b16b682..c1c1ade1ff 100644 --- a/features/home/impl/src/main/res/values-ja/translations.xml +++ b/features/home/impl/src/main/res/values-ja/translations.xml @@ -38,7 +38,7 @@ "低い優先度のチャットはまだありません" "フィルターを解除して他のチャットを表示できます" "この選択中にチャットがありません" - "人" + "人々" "まだダイレクトメッセージは届いていません" "ルーム" "まだルームに参加していません" diff --git a/features/home/impl/src/main/res/values-uz/translations.xml b/features/home/impl/src/main/res/values-uz/translations.xml index e5ef24e80a..6079389609 100644 --- a/features/home/impl/src/main/res/values-uz/translations.xml +++ b/features/home/impl/src/main/res/values-uz/translations.xml @@ -5,9 +5,9 @@ "Bildirishnoma kelmayaptimi?" "Xabarnoma signali yangilandi — endi u aniqroq, tezroq va kamroq halal beradigan bo‘ldi." "Tovushlaringiz yangilandi" - "Mavjud barcha qurilmalarni yoʻqotgan boʻlsangiz, kriptografik kimligingizni va xabarlar tarixini qayta tiklovchi kalit bilan saqlab qoʻying." + "Chatlaringiz avtomatik ravishda boshidan oxirigacha shifrlash bilan zaxiralanadi. Bu zaxirani tiklash va barcha qurilmalaringizdan foydalana olmay qolganingizda raqamli identifikatoringizni saqlab qolish uchun sizga tiklash kaliti kerak bo‘ladi." "Qayta tiklashni sozlang" - "Hisobingizni himoya qilish uchun tiklashni sozlang" + "Chatlaringizni zaxiralang" "Kalit saqlash joyingiz va xabarlar tarixingizga kirishni saqlab qolish uchun tiklash kalitingizni tasdiqlang." "Qayta tiklash kalitingizni kiriting" "Tiklash kalitini unutdingizmi?" @@ -50,6 +50,7 @@ Sizda oʻqilmagan xabarlar yoʻq!" "Oʻqilgan deb belgilash" "Oʻqilmagan deb belgilash" "Bu xona yangilandi" + "Maydonlaringiz" "Siz yangi qurilmadan foydalanayotganga o‘xshaysiz. Shifrlangan xabarlaringizga kirish uchun boshqa qurilma bilan tasdiqlang." "Siz ekanligingizni tasdiqlang" diff --git a/features/home/impl/src/main/res/values-vi/translations.xml b/features/home/impl/src/main/res/values-vi/translations.xml index bc62880fff..49fdaf46c9 100644 --- a/features/home/impl/src/main/res/values-vi/translations.xml +++ b/features/home/impl/src/main/res/values-vi/translations.xml @@ -12,6 +12,8 @@ "Nhập khóa khôi phục của bạn." "Bạn quên khóa khôi phục?”" "Dữ liệu khóa của bạn không còn đồng bộ" + "Để đảm bảo bạn không bỏ lỡ bất kỳ cuộc gọi quan trọng nào, vui lòng thay đổi cài đặt để cho phép thông báo toàn màn hình khi điện thoại của bạn bị khóa." + "Nâng cao trải nghiệm cuộc gọi của bạn" "Cuộc trò chuyện" "Bạn có chắc muốn từ chối lời mời tham gia %1$s không?" "Từ chối lời mời" diff --git a/features/home/impl/src/main/res/values-zh-rTW/translations.xml b/features/home/impl/src/main/res/values-zh-rTW/translations.xml index 20ee59da98..b52ac9ad8b 100644 --- a/features/home/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/home/impl/src/main/res/values-zh-rTW/translations.xml @@ -5,9 +5,9 @@ "沒收到通知?" "您的通知提示音已更新,更清晰、更快、更不易分心。" "我們已更新您的音效設定" - "若您遺失了所有現有裝置,則請使用復原金鑰以救援您的密碼學身份與訊息歷史紀錄。" - "設定復原" - "設定備援以保護您的帳號" + "您的聊天會自動使用端到端加密備份。若您失去對您所有裝置的存取權,且要還原此備份並保留您的數位身份的話,您就會需要您的還原金鑰。" + "取得還原金鑰" + "備份您的聊天" "確認您的復原金鑰以維持對金鑰儲存空間與訊息歷史紀錄的存取權。" "輸入您的復原金鑰" "忘記了您的復原金鑰?" @@ -50,6 +50,7 @@ "標為已讀" "標為未讀" "此聊天室已升級" + "您的空間" "您似乎正在使用新的裝置。請使用另一個裝置進行驗證,以存取您的加密訊息。" "驗證這是您本人" diff --git a/features/home/impl/src/main/res/values-zh/translations.xml b/features/home/impl/src/main/res/values-zh/translations.xml index 58e5b1eb91..e0704c52a6 100644 --- a/features/home/impl/src/main/res/values-zh/translations.xml +++ b/features/home/impl/src/main/res/values-zh/translations.xml @@ -7,7 +7,7 @@ "我们已更新您的声音" "生成新的恢复密钥,该密钥可用于在您无法访问设备时恢复加密的消息历史记录。" "获取恢复密钥" - "设置恢复" + "备份聊天" "确认恢复密钥,以保持对密钥存储和消息历史的访问。" "输入恢复密钥" "忘记了恢复密钥?" diff --git a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt index 38db9d55be..e8ce5222eb 100644 --- a/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt +++ b/features/invitepeople/impl/src/main/kotlin/io/element/android/features/invitepeople/impl/InvitePeopleView.kt @@ -23,7 +23,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable 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 @@ -264,8 +263,16 @@ private fun InvitePeopleConfirmModal( dragHandle = null, ) { IconTitleSubtitleMolecule( - title = pluralStringResource(R.plurals.screen_invite_users_confirm_dialog_title, users.size), - subTitle = pluralStringResource(R.plurals.screen_invite_users_confirm_dialog_subtitle, users.size), + title = if (users.size > 1) { + stringResource(R.string.screen_invite_users_confirm_dialog_title_mutiple_users) + } else { + stringResource(R.string.screen_invite_users_confirm_dialog_title_one_user) + }, + subTitle = if (users.size > 1) { + stringResource(R.string.screen_invite_users_confirm_dialog_subtitle_multiple_users) + } else { + stringResource(R.string.screen_invite_users_confirm_dialog_subtitle_one_user) + }, iconStyle = BigIcon.Style.Default(CompoundIcons.UserAddSolid()), modifier = Modifier.padding( top = 32.dp, diff --git a/features/invitepeople/impl/src/main/res/values-ja/translations.xml b/features/invitepeople/impl/src/main/res/values-ja/translations.xml index 6aa1fb0370..eefa446d79 100644 --- a/features/invitepeople/impl/src/main/res/values-ja/translations.xml +++ b/features/invitepeople/impl/src/main/res/values-ja/translations.xml @@ -2,10 +2,4 @@ "既に参加しています" "既に招待しています" - - "この連絡先とのチャットがありません。続行する前に、このルームに招待してください。" - - - "このルームに新しい連絡先を追加しますか?" - diff --git a/features/invitepeople/impl/src/main/res/values/localazy.xml b/features/invitepeople/impl/src/main/res/values/localazy.xml index 0515121428..aae71fe4c2 100644 --- a/features/invitepeople/impl/src/main/res/values/localazy.xml +++ b/features/invitepeople/impl/src/main/res/values/localazy.xml @@ -2,12 +2,8 @@ "Already a member" "Already invited" - - "You currently don’t have any chats with this contact. Confirm inviting them to this room before continuing." - "You currently don’t have any chats with these contacts. Confirm inviting them to this room before continuing." - - - "Invite a new contact to this room?" - "Invite new contacts to this room?" - + "You currently don’t have any chats with these contacts. Confirm inviting them to this room before continuing." + "You currently don’t have any chats with this contact. Confirm inviting them to this room before continuing." + "Invite new contacts to this room?" + "Invite new contact to this room?" diff --git a/features/joinroom/impl/src/main/res/values-vi/translations.xml b/features/joinroom/impl/src/main/res/values-vi/translations.xml index cb9258b308..bf5c33ba66 100644 --- a/features/joinroom/impl/src/main/res/values-vi/translations.xml +++ b/features/joinroom/impl/src/main/res/values-vi/translations.xml @@ -1,5 +1,7 @@ + "Bạn đã bị cấm bởi %1$s ." + "Bạn đã bị cấm" "Hủy yêu cầu" "Có, hủy" "Bạn có chắc chắn muốn hủy yêu cầu tham gia phòng này không?" diff --git a/features/knockrequests/impl/src/main/res/values-vi/translations.xml b/features/knockrequests/impl/src/main/res/values-vi/translations.xml index a80aa6fbb8..ab7c39c2ef 100644 --- a/features/knockrequests/impl/src/main/res/values-vi/translations.xml +++ b/features/knockrequests/impl/src/main/res/values-vi/translations.xml @@ -24,6 +24,9 @@ "Khi ai đó xin vào phòng, bạn sẽ thấy yêu cầu ở đây." "Không có yêu cầu tham gia nào đang chờ xử lý" "Đang tải các yêu cầu tham gia…" + + "%1$s + %2$d người khác muốn tham gia phòng này" + "Đồng ý" "Xem" diff --git a/features/leaveroom/api/src/main/res/values-vi/translations.xml b/features/leaveroom/api/src/main/res/values-vi/translations.xml index d25a7e34b2..430ffa0ea3 100644 --- a/features/leaveroom/api/src/main/res/values-vi/translations.xml +++ b/features/leaveroom/api/src/main/res/values-vi/translations.xml @@ -3,5 +3,8 @@ "Bạn có chắc chắn muốn rời khỏi cuộc trò chuyện này không? Cuộc trò chuyện này không công khai và bạn sẽ không thể tham gia lại nếu không được mời." "Bạn có chắc chắn muốn rời khỏi phòng này không? Bạn là người duy nhất ở đây. Nếu bạn rời đi, sẽ không ai có thể tham gia nữa, kể cả bạn." "Bạn có chắc chắn muốn rời khỏi phòng này không? Phòng này không công khai và bạn sẽ không thể tham gia lại nếu không có lời mời." + "Chọn chủ sở hữu" + "Bạn là chủ sở hữu duy nhất của căn phòng này. Bạn cần chuyển quyền sở hữu cho người khác trước khi rời khỏi phòng." + "Chuyển quyền sở hữu" "Bạn có chắc chắn muốn rời khỏi phòng không?" diff --git a/features/linknewdevice/impl/src/main/res/values-uz/translations.xml b/features/linknewdevice/impl/src/main/res/values-uz/translations.xml index b1f3deebf4..ed08ee1a04 100644 --- a/features/linknewdevice/impl/src/main/res/values-uz/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-uz/translations.xml @@ -26,6 +26,7 @@ "QR kod yuklanmoqda…" "Mobil qurilma" "Qaysi turdagi qurilmani bog‘lashni xohlaysiz?" + "Qayta urining va 2 xonali kodni bexato kiritganingizni tekshiring. Agar raqamlar hali ham mos kelmasa, hisobingiz provayderiga murojaat qiling." "Raqamlar mos kelmaydi" "Yangi qurilmaga xavfsiz ulanish amalga oshirilmadi. Mavjud qurilmalaringiz hali ham xavfsiz va ular haqida qaygʻurishingiz shart emas." "Endi nima?" @@ -37,6 +38,8 @@ "Tizimga kirish soʻrovi bekor qilindi" "Boshqa qurilmadan hisobga kirish bekor qilindi." "Tizimga kirish rad etildi" + "Boshqa hech narsa qilishingiz shart emas." + "Boshqa qurilmangiz allaqachon tizimga kirgan" "Kirish muddati tugagan. Iltimos, qayta urinib koʻring." "Kirish oʻz vaqtida tugallanmagan" "Boshqa qurilmangiz %s hisobiga QR kod orqali kirishni qoʻllab-quvvatlamaydi. diff --git a/features/linknewdevice/impl/src/main/res/values-zh-rTW/translations.xml b/features/linknewdevice/impl/src/main/res/values-zh-rTW/translations.xml index 9b3cd5ead5..3aa047125a 100644 --- a/features/linknewdevice/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/linknewdevice/impl/src/main/res/values-zh-rTW/translations.xml @@ -1,16 +1,33 @@ "掃描 QR code" + "在筆記型電腦或桌上型電腦上開啟 %1$s" "使用此裝置掃描 QR code" "準備掃描" + "在桌上型電腦上開啟 %1$s 以取得 QR code" + "數字不符" + "輸入兩位數代碼" + "這將確認您與另一台裝置之間的連線是否安全。" + "輸入顯示在您的其他裝置上的數字" "您的帳號提供者不支援 %1$s。" "不支援 %1$s" + "您的帳號提供者不支援使用 QR code 登入新裝置。" "不支援 QR code" "已在其他裝置上取消登入。" "已取消登入請求" "登入已過期。請再試一次。" "未及時完成登入" + "在其他裝置上開啟 %1$s" "選取 %1$s" + "「使用 QR code 登入」" + "使用其他裝置掃描此處顯示的 QR code" + "在其他裝置上開啟 %1$s" + "桌上型電腦" + "正在載入 QR code……" + "行動裝置" + "您想連結哪種類型的裝置?" + "請重試,並確定您已輸入兩位數代碼。若數字仍然不符,請聯絡您的帳號提供者。" + "數字不符" "無法與新裝置建立安全連線。您現有的裝置仍然安全,您不必擔心它們。" "現在怎麼辦?" "嘗試再次使用 QR code 登入以確認不是網路問題" @@ -21,6 +38,8 @@ "已取消登入請求" "其他裝置拒絕登入。" "已拒絕登入" + "您不需要進行其他操作。" + "您的其他裝置已登入" "登入已過期。請再試一次。" "未及時完成登入" "您的其他裝置不支援使用 QR cpde 登入 %s。 diff --git a/features/location/impl/src/main/res/values-de/translations.xml b/features/location/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..1a1e208c3b --- /dev/null +++ b/features/location/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,4 @@ + + + "Wie lange soll der Live-Standort geteilt werden?" + diff --git a/features/location/impl/src/main/res/values-fi/translations.xml b/features/location/impl/src/main/res/values-fi/translations.xml index bc7e84e7b0..4a7d801f71 100644 --- a/features/location/impl/src/main/res/values-fi/translations.xml +++ b/features/location/impl/src/main/res/values-fi/translations.xml @@ -1,4 +1,5 @@ + "Reaaliaikainen sijaintihistoriasi tallennetaan huoneeseen ja on jäsenten nähtävissä istunnon päätyttyä." "Valitse, kuinka kauan haluat jakaa reaaliaikaisen sijaintisi." diff --git a/features/location/impl/src/main/res/values-hr/translations.xml b/features/location/impl/src/main/res/values-hr/translations.xml new file mode 100644 index 0000000000..0a294ade1b --- /dev/null +++ b/features/location/impl/src/main/res/values-hr/translations.xml @@ -0,0 +1,5 @@ + + + "Vaša povijest lokacije uživo bit će pohranjena u sobi i vidljiva članovima nakon završetka sesije." + "Odaberite koliko dugo želite dijeliti svoju lokaciju uživo." + diff --git a/features/location/impl/src/main/res/values-uz/translations.xml b/features/location/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..2b10808d85 --- /dev/null +++ b/features/location/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,5 @@ + + + "Jonli joylashuv tarixingiz chat-xonada saqlanadi va sessiya tugaganidan keyin homiylarga ko‘rinadi." + "Jonli joylashuvingiz qancha vaqt ulashilishini tanlang." + diff --git a/features/location/impl/src/main/res/values-zh-rTW/translations.xml b/features/location/impl/src/main/res/values-zh-rTW/translations.xml new file mode 100644 index 0000000000..27f507732d --- /dev/null +++ b/features/location/impl/src/main/res/values-zh-rTW/translations.xml @@ -0,0 +1,5 @@ + + + "您的即時位置歷史將儲存於聊天室中,並在工作階段結束後對其他成員可見。" + "選擇分享即時位置的時間長度。" + diff --git a/features/lockscreen/impl/src/main/res/values-de/translations.xml b/features/lockscreen/impl/src/main/res/values-de/translations.xml index dd74818610..e1819583f0 100644 --- a/features/lockscreen/impl/src/main/res/values-de/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-de/translations.xml @@ -23,7 +23,7 @@ Wähle eine einprägsame PIN. Wenn du sie vergisst, wirst du aus der App abgemel "Bitte gib die gleiche PIN wie zuvor ein." "Die PINs stimmen nicht überein" "Um fortzufahren, musst du dich erneut anmelden und eine neue PIN erstellen" - "Du wirst abgemeldet" + "Dieses Gerät wurde entfernt" "Du hast %1$d Versuch, um zu entsperren" "Du hast %1$d Versuche, um zu entsperren" @@ -34,5 +34,5 @@ Wähle eine einprägsame PIN. Wenn du sie vergisst, wirst du aus der App abgemel "Biometrie verwenden" "PIN verwenden" - "Abmelden…" + "Gerät wird entfernt…" diff --git a/features/lockscreen/impl/src/main/res/values-et/translations.xml b/features/lockscreen/impl/src/main/res/values-et/translations.xml index 4449479ba6..ac25914f8c 100644 --- a/features/lockscreen/impl/src/main/res/values-et/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-et/translations.xml @@ -23,7 +23,7 @@ Vali midagi, mis hästi meelde jääb. Kui unustad selle PIN-koodi, siis turvaka "Palun sisesta sama PIN-kood kaks korda" "PIN-koodid ei klapi omavahel" "Jätkamaks pead uuesti sisse logima ja looma uue PIN-koodi" - "Sa oled logimas välja" + "See seade on eemaldamisel" "Sul on lukustuse eemaldamiseks jäänud %1$d katse" "Sul on lukustuse eemaldamiseks jäänud %1$d katset" diff --git a/features/lockscreen/impl/src/main/res/values-hr/translations.xml b/features/lockscreen/impl/src/main/res/values-hr/translations.xml index 1a81bcc6cb..232775c798 100644 --- a/features/lockscreen/impl/src/main/res/values-hr/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-hr/translations.xml @@ -23,7 +23,7 @@ Odaberite nešto nezaboravno. Ako zaboravite ovaj PIN, bit ćete odjavljeni iz a "Unesite dvaput isti PIN" "PIN-ovi se ne podudaraju" "Morat ćete se ponovno prijaviti i izraditi novi PIN da biste mogli nastaviti" - "Odjavit ćete se" + "Ovaj uređaj se uklanja" "Imate %1$d pokušaj otključavanja" "Imate %1$d pokušaja otključavanja" @@ -36,5 +36,5 @@ Odaberite nešto nezaboravno. Ako zaboravite ovaj PIN, bit ćete odjavljeni iz a "Upotrijebi biometriju" "Upotrijebi PIN" - "Odjavljivanje…" + "Uklanjanje uređaja…" diff --git a/features/lockscreen/impl/src/main/res/values-vi/translations.xml b/features/lockscreen/impl/src/main/res/values-vi/translations.xml index 2a177b843b..59dd89b114 100644 --- a/features/lockscreen/impl/src/main/res/values-vi/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-vi/translations.xml @@ -3,6 +3,7 @@ "xác thực sinh trắc học" "mở khóa sinh trắc học" "Mở khóa bằng sinh trắc học" + "Xác nhận sinh trắc học" "Quên mã PIN rồi à?" "Thay đổi mã PIN" "Cho phép mở khóa bằng sinh trắc học" diff --git a/features/lockscreen/impl/src/main/res/values-zh-rTW/translations.xml b/features/lockscreen/impl/src/main/res/values-zh-rTW/translations.xml index 799db8f84c..2bd329aea4 100644 --- a/features/lockscreen/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-zh-rTW/translations.xml @@ -23,7 +23,7 @@ "請輸入相同的 PIN 碼兩次" "PIN 碼不一樣" "您需要重新登入並建立新的 PIN 碼才能繼續" - "您即將登出" + "此裝置已被移除" "您有 %1$d 次解鎖的機會" @@ -32,5 +32,5 @@ "使用生物辨識" "使用 PIN 碼" - "正在登出…" + "正在移除裝置……" diff --git a/features/lockscreen/impl/src/main/res/values-zh/translations.xml b/features/lockscreen/impl/src/main/res/values-zh/translations.xml index defe7a0e32..b83c7d4e85 100644 --- a/features/lockscreen/impl/src/main/res/values-zh/translations.xml +++ b/features/lockscreen/impl/src/main/res/values-zh/translations.xml @@ -23,7 +23,7 @@ "请输入两次相同的 PIN 码" "PIN 码不匹配" "您需要重新登录并创建新的 PIN 才能继续" - "您正在登出" + "正在被移除该设备" "还剩 %1$d 次解锁机会" diff --git a/features/login/impl/src/main/res/values-cs/translations.xml b/features/login/impl/src/main/res/values-cs/translations.xml index 73f0dd51cc..6146f1776d 100644 --- a/features/login/impl/src/main/res/values-cs/translations.xml +++ b/features/login/impl/src/main/res/values-cs/translations.xml @@ -42,6 +42,7 @@ "Přihlaste se k %1$s" "Přihlásit se pomocí QR kódu" "Vytvořit účet" + "Vítejte zpět" "Vítejte v dosud nejrychlejším %1$su. Vylepšený pro rychlost a jednoduchost." "Vítejte v %1$su. Vylepšený, pro rychlost a jednoduchost." "Buďte ve svém živlu" diff --git a/features/login/impl/src/main/res/values-da/translations.xml b/features/login/impl/src/main/res/values-da/translations.xml index 2b2f00267b..284284cc3e 100644 --- a/features/login/impl/src/main/res/values-da/translations.xml +++ b/features/login/impl/src/main/res/values-da/translations.xml @@ -42,6 +42,7 @@ "Log ind på %1$s" "Log ind med QR-kode" "Opret konto" + "Velkommen tilbage" "Velkommen til den hurtigste %1$s nogensinde. Supercharged til hastighed og enkelhed." "Velkommen til %1$s. Ladet med hastighed og enkelhed." "Vær i dit rette Element" diff --git a/features/login/impl/src/main/res/values-de/translations.xml b/features/login/impl/src/main/res/values-de/translations.xml index f1d426e134..dced91a1c9 100644 --- a/features/login/impl/src/main/res/values-de/translations.xml +++ b/features/login/impl/src/main/res/values-de/translations.xml @@ -5,9 +5,9 @@ "Gib einen Suchbegriff oder eine Domainadresse ein." "Suche nach einem Unternehmen, einer Community oder einem privaten Server." "Kontoanbieter finden" - "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würden." + "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würdest." "Du bist dabei, dich bei %s anzumelden" - "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würden." + "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würdest." "Du bist dabei, ein Konto bei %s zu erstellen" "Matrix.org ist ein großer, kostenloser Server im öffentlichen Matrix-Netzwerk für eine sichere, dezentralisierte Kommunikation, der von der Matrix.org Foundation betrieben wird." "Sonstige" @@ -42,6 +42,7 @@ "Anmelden bei %1$s" "Mit QR-Code anmelden" "Konto erstellen" + "Willkommen zurück" "Willkommen beim schnellsten %1$s aller Zeiten. Optimiert für Geschwindigkeit und Einfachheit." "Willkommen zu %1$s. Aufgeladen, für Geschwindigkeit und Einfachheit." "Sei in Deinem Element" @@ -93,7 +94,7 @@ Versuche, dich manuell anzumelden, oder scanne den QR-Code mit einem anderen Ger "Kontoanbieter wechseln" "Ein privater Server für die Mitarbeiter von Element." "Matrix ist ein offenes Netzwerk für eine sichere, dezentrale Kommunikation." - "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würden." + "Hier werden deine Gespräche gespeichert - so wie du deine E-Mails bei einem E-Mail-Anbieter aufbewahren würdest." "Du bist dabei, dich bei %1$s anzumelden" "Kontoanbieter auswählen" "Du bist dabei, auf %1$s ein Konto zu erstellen" 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 5f21a53c37..c87027477d 100644 --- a/features/login/impl/src/main/res/values-el/translations.xml +++ b/features/login/impl/src/main/res/values-el/translations.xml @@ -42,6 +42,7 @@ "Συνδέσου στο %1$s" "Συνδέσου με κωδικό QR" "Δημιουργία λογαριασμού" + "Καλώς ήρθατε ξανά" "Καλώς ήλθατε στο γρηγορότερο %1$s όλων των εποχών. Υπερτροφοδοτούμενο με ταχύτητα και απλότητα." "Καλώς ήρθες στο %1$s. Υπερφορτισμένο, για ταχύτητα και απλότητα." "Μείνε στο element σου" diff --git a/features/login/impl/src/main/res/values-et/translations.xml b/features/login/impl/src/main/res/values-et/translations.xml index 0a1a99383d..7ac4e99694 100644 --- a/features/login/impl/src/main/res/values-et/translations.xml +++ b/features/login/impl/src/main/res/values-et/translations.xml @@ -37,11 +37,14 @@ "Matrix on avatud võrk turvalise ja hajutatud suhtluse jaoks." "Tere tulemast tagasi!" "Logi sisse serverisse %1$s" + "Ava Element Classic" + "Ava Element Classic oma seadmes" "Versioon %1$s" "Logi sisse käsitsi" "Logi sisse serverisse %1$s" "Logi sisse QR-koodi alusel" "Loo kasutajakonto" + "Tere tulemast tagasi" "Läbi aegade kiireim ja mugavaim %1$s." "Tere tulemast kasutama kiiret ja lihtsat suhtlusrakendust %1$s." "Ole oma elemendis" diff --git a/features/login/impl/src/main/res/values-fi/translations.xml b/features/login/impl/src/main/res/values-fi/translations.xml index af8e242309..0d795811b1 100644 --- a/features/login/impl/src/main/res/values-fi/translations.xml +++ b/features/login/impl/src/main/res/values-fi/translations.xml @@ -37,11 +37,20 @@ "Matrix on avoin verkko turvallista, hajautettua viestintää varten." "Tervetuloa takaisin!" "Kirjaudu sisään %1$s -palvelimelle" + "Avaa Element Classic" + "Avaa Element Classic laitteellasi" + "Mene kohtaan Asetukset > Tietoturva ja yksityisyys" + "Osiossa \"Salausavainten hallinta\", paina \"Salattujen viestien palautus\"." + "Noudata ohjeita" + "Palaa takaisin %1$s -sovellukseen" + "Ota avainten säilytys käyttöön ennen kuin jatkat %1$s -sovellukseen" "Versio %1$s" + "Tarkistetaan tiliä…" "Kirjaudu sisään manuaalisesti" "Kirjaudu sisään %1$s -palvelimelle" "Kirjaudu sisään QR-koodilla" "Luo tili" + "Tervetuloa takaisin" "Tervetuloa kaikkien aikojen nopeimpaan %1$s -sovellukseen. Ahdettu nopeudella ja yksinkertaisuudella." "Tervetuloa %1$s -sovellukseen. Ahdettu nopeudella ja yksinkertaisuudella." "Ole elementissäsi" diff --git a/features/login/impl/src/main/res/values-fr/translations.xml b/features/login/impl/src/main/res/values-fr/translations.xml index 9846feec38..3435eb7d40 100644 --- a/features/login/impl/src/main/res/values-fr/translations.xml +++ b/features/login/impl/src/main/res/values-fr/translations.xml @@ -37,11 +37,20 @@ "Matrix est un réseau ouvert pour une communication sécurisée et décentralisée." "Content de vous revoir !" "Connectez-vous à %1$s" + "Ouvrir Element Classic" + "Ouvrez Element Classic sur votre appareil" + "Aller à Paramètres > Sécurité et vie privée" + "Dans Gestion des clés cryptographiques, sélectionnez Récupération des messages chiffrés" + "Suivez les instructions pour activer votre stockage de clés" + "Revenez à %1$s" + "Activez le stockage de vos clés avant de continuer avec %1$s" "Version %1$s" + "Vérification du compte" "Se connecter manuellement" "Connectez-vous à %1$s" "Se connecter avec un code QR" "Créer un compte" + "Bon retour parmi nous" "Bienvenue dans l’application %1$s la plus rapide de tous les temps. Boosté pour plus de rapidité et de simplicité." "Bienvenue sur %1$s. Boosté, pour plus de rapidité et de simplicité." "Soyez dans votre Element" diff --git a/features/login/impl/src/main/res/values-hr/translations.xml b/features/login/impl/src/main/res/values-hr/translations.xml index ced196f87e..b52dd77d7f 100644 --- a/features/login/impl/src/main/res/values-hr/translations.xml +++ b/features/login/impl/src/main/res/values-hr/translations.xml @@ -37,11 +37,20 @@ "Matrix je otvorena mreža za sigurnu, decentraliziranu komunikaciju." "Dobro došli natrag!" "Prijavi se na poslužitelj %1$s" + "Pokreni Element Classic" + "Otvorite Element Classic na svom uređaju" + "Idite na Postavke > Sigurnost i privatnost" + "šifrirane poruke" + "Slijedite upute za omogućavanje pohrane ključeva" + "Vrati se %1$s" + "Omogućite pohranu ključeva prije nego što nastavite na %1$s" "Inačica %1$s" + "Provjera računa…" "Prijavi se ručno" "Prijavi se na poslužitelj %1$s" "Prijavi se pomoću QR koda" "Izradi račun" + "Dobro došli natrag!" "Dobro došli u nikad brži %1$s. Snažniji no ikad za postizanje brzine i jednostavnosti." "Dobro došli u %1$s. Snažniji no ikad – za brzinu i jednostavnost." "Budi u elementu" diff --git a/features/login/impl/src/main/res/values-hu/translations.xml b/features/login/impl/src/main/res/values-hu/translations.xml index 06014b77b7..c2b2fefddb 100644 --- a/features/login/impl/src/main/res/values-hu/translations.xml +++ b/features/login/impl/src/main/res/values-hu/translations.xml @@ -37,11 +37,20 @@ "A Matrix egy nyitott hálózat a biztonságos, decentralizált kommunikációhoz." "Örülünk, hogy visszatért!" "Bejelentkezés ide: %1$s" + "Nyissa meg az Element Classic alkalmazást" + "Nyissa meg az Element Classic alkalmazást az eszközén" + "Lépjen a Beállítások > Biztonság és adatvédelem menüponthoz" + "A Kriptográfiai kulcsok kezelése részben válassza a Titkosított üzenetek helyreállítása lehetőséget" + "Kövesse az utasításokat a kulcstároló engedélyezéséhez" + "Térjen vissza ide: %1$s" + "Engedélyezze a kulcstárolást a folytatás előtt ide: %1$s" "Verzió: %1$s" + "Fiók ellenőrzése" "Kézi bejelentkezés" "Bejelentkezés ide: %1$s" "Bejelentkezés QR-kóddal" "Fiók létrehozása" + "Üdvözöljük újra!" "Üdvözöljük a valaha volt leggyorsabb %1$sben. Felturbózva, a sebesség és az egyszerűség érdekében." "Üdvözli az %1$s. Felturbózva, a sebesség és az egyszerűség jegyében." "Legyen elemében" 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 0de1cc0690..e882654e4b 100644 --- a/features/login/impl/src/main/res/values-it/translations.xml +++ b/features/login/impl/src/main/res/values-it/translations.xml @@ -37,11 +37,19 @@ "Matrix è una rete aperta per comunicazioni sicure e decentralizzate." "Bentornato!" "Accedi a %1$s" + "Apri Element Classic" + "Apri Element Classic sul tuo dispositivo" + "Vai su Impostazioni > Sicurezza & privacy" + "Nella gestione delle chiavi crittografiche, seleziona Recupero dei messaggi cifrati" + "Segui le istruzioni per abilitare l\'archiviazione delle chiavi" + "Torna a %1$s" + "Abilita l\'archivio delle chiavi prima di procedere con %1$s" "Versione %1$s" "Accedi manualmente" "Accedi a %1$s" "Accedi con codice QR" "Crea account" + "Bentornato" "Benvenuti nell\'%1$s più veloce di sempre. Potenziato per velocità e semplicità." "Benvenuto su %1$s. Potenziato in velocità e semplicità." "Sii nel tuo elemento" diff --git a/features/login/impl/src/main/res/values-ja/translations.xml b/features/login/impl/src/main/res/values-ja/translations.xml index e2c89ba26e..219605ab22 100644 --- a/features/login/impl/src/main/res/values-ja/translations.xml +++ b/features/login/impl/src/main/res/values-ja/translations.xml @@ -36,11 +36,20 @@ "Matrix は安全で分散型のオープンなネットワークです。" "お待ちしておりました。" "%1$s にサインイン" + "Element Classic を開く" + "Element Classic をこの端末で開く" + "「設定- セキュリティとプライバシー」に移動します" + "暗号鍵の管理から、暗号化されたメッセージの回復を選択します" + "指示に従って、鍵の保管庫を有効化してください" + "%1$s に戻ってください" + "%1$s に続行する前に、鍵の保管庫を有効化してください" "バージョン %1$s" + "アカウントを確認中" "手動で指定してサインイン" "%1$s にサインイン" "QRコードでサインイン" "アカウントを作成" + "おかえりなさい" "最速の %1$s にようこそ。機能性と利便性を極限まで追求しました。" "機敏と利便を追求した %1$s へようこそ。" "Be in your element" diff --git a/features/login/impl/src/main/res/values-ko/translations.xml b/features/login/impl/src/main/res/values-ko/translations.xml index 69bf12cdb0..c870377fc4 100644 --- a/features/login/impl/src/main/res/values-ko/translations.xml +++ b/features/login/impl/src/main/res/values-ko/translations.xml @@ -37,11 +37,19 @@ "Matrix 는 안전하고 분산된 커뮤니케이션을 위한 개방형 네트워크입니다." "다시 돌아온 걸 환영합니다!" "%1$s 에 로그인합니다" + "Element Classic 열기" + "기기에서 Element Classic 앱을 열어 주세요" + "설정 > 보안 및 개인정보 보호로 이동하세요" + "암호화 키 관리에서 \'암호화된 메시지 복구\'를 선택하세요" + "안내에 따라 키 저장소를 활성화해 주세요" + "%1$s(으)로 돌아가기" + "%1$s(으)로 진행하기 전에 키 저장소를 활성화해 주세요." "버전 %1$s" "수동으로 로그인" "%1$s 에 로그인합니다" "QR 코드로 로그인" "계정 만들기" + "다시 오신 것을 환영합니다" "%1$s 에 오신 것을 환영합니다. 속도와 단순성을 극대화한 가장 빠른 버전입니다." "%1$s 에 오신 것을 환영합니다. 속도와 단순성을 위해 최적화된 앱입니다." "당신의 엘리먼트에 있어" diff --git a/features/login/impl/src/main/res/values-lt/translations.xml b/features/login/impl/src/main/res/values-lt/translations.xml index f8f243f29d..870e2c4d31 100644 --- a/features/login/impl/src/main/res/values-lt/translations.xml +++ b/features/login/impl/src/main/res/values-lt/translations.xml @@ -41,6 +41,7 @@ "Prisijungti prie %1$s" "Prisijungti su QR kodu" "Kurti paskyrą" + "Sveiki sugrįžę" "Sveiki atvykę į sparčiausią „%1$s“ kada nors. Pagerintas spartai ir paprastumui." "Sveiki atvykę į „%1$s“. Pagerintas spartai ir paprastumui." "Būkite savo stichijoje" diff --git a/features/login/impl/src/main/res/values-nb/translations.xml b/features/login/impl/src/main/res/values-nb/translations.xml index 3233329f86..5957b902ce 100644 --- a/features/login/impl/src/main/res/values-nb/translations.xml +++ b/features/login/impl/src/main/res/values-nb/translations.xml @@ -42,6 +42,7 @@ "Logg inn på %1$s" "Logg inn med QR-kode" "Opprett konto" + "Velkommen tilbake" "Velkommen til den raskeste %1$s noensinne. Superladet for hastighet og enkelhet." "Velkommen til %1$s. Supercharged, for hastighet og enkelhet." "Vær i ditt rette element" diff --git a/features/login/impl/src/main/res/values-ru/translations.xml b/features/login/impl/src/main/res/values-ru/translations.xml index b967224f2e..4437c19056 100644 --- a/features/login/impl/src/main/res/values-ru/translations.xml +++ b/features/login/impl/src/main/res/values-ru/translations.xml @@ -37,11 +37,20 @@ "Matrix — это открытая сеть для безопасной децентрализованной связи." "Рады видеть вас снова!" "Войти в %1$s" + "Открыть Element Classic" + "Откройте Element Classic на своем устройстве." + "Перейдите в Настройки > Безопасность и конфиденциальность" + "В разделе «Управление криптографическими ключами» выбери «Восстановление зашифрованных сообщений»" + "Следуйте инструкциям, чтобы активировать хранилище ключей" + "Вернитесь к %1$s" + "Перед продолжением активируйте хранилище ключей %1$s" "Версия %1$s" + "Проверка аккаунта" "Войти" "Войти в %1$s" "Войти с QR-кодом" "Создать аккаунт" + "С возвращением" "Добро пожаловать в быстрый и простой %1$s." "Добро пожаловать в быстрый и простой %1$s." "Элементарно." diff --git a/features/login/impl/src/main/res/values-uz/translations.xml b/features/login/impl/src/main/res/values-uz/translations.xml index 54a1cf11cc..07b3d8835b 100644 --- a/features/login/impl/src/main/res/values-uz/translations.xml +++ b/features/login/impl/src/main/res/values-uz/translations.xml @@ -36,11 +36,20 @@ "Matrix xavfsiz, markazlashmagan aloqa uchun ochiq tarmoqdir." "Qaytib kelganingizdan xursandmiz!" "Kirish%1$s" + "Element Classic ilovasini ochish" + "Element Classic ilovasini qurilmada oching" + "Sozlamalar > Xavfsizlik va maxfiylik bo‘limiga kiring" + "Kriptografiya kalitlarini boshqarishda Shifrlangan xabarlarni tiklash bandini tanlang" + "Kalit xotirasini yoqish uchun ko‘rsatmalarga amal qiling" + "%1$sga qaytish" + "%1$s xizmatiga o‘tishdan oldin kalit xotirasini yoqing" "%1$s versiya" + "Joriy hisob" "Qo\'lda tizimga kiring" "Kirish%1$s" "QR kod bilan tizimga kiring" "Hisob yaratish" + "Xush kelibsiz." "Eng tezkor %1$sga xush kelibsiz. Tezlik va oddiylik uchun super zaryadlangan." "%1$sga Xush kelibsiz. Tezlik va oddiylik uchun o\'ta zaryadlangan." "Elementingizda bo\'ling" @@ -59,6 +68,8 @@ "Tizimga kirish soʻrovi bekor qilindi" "Boshqa qurilmadan hisobga kirish bekor qilindi." "Tizimga kirish rad etildi" + "Boshqa hech narsa qilishingiz shart emas." + "Boshqa qurilmangiz allaqachon tizimga kirgan" "Kirish muddati tugagan. Iltimos, qayta urinib koʻring." "Kirish oʻz vaqtida tugallanmagan" "Boshqa qurilmangiz %s hisobiga QR kod orqali kirishni qoʻllab-quvvatlamaydi. diff --git a/features/login/impl/src/main/res/values-vi/translations.xml b/features/login/impl/src/main/res/values-vi/translations.xml index b22ba5de7c..4d9b921ea5 100644 --- a/features/login/impl/src/main/res/values-vi/translations.xml +++ b/features/login/impl/src/main/res/values-vi/translations.xml @@ -13,9 +13,16 @@ "Khác" "Sử dụng nhà cung cấp tài khoản khác, ví dụ như máy chủ riêng của bạn hoặc tài khoản công việc." "Thay đổi nhà cung cấp tài khoản" + "Google Play" + "Ứng dụng Element Pro là bắt buộc trên %1$s. Vui lòng tải xuống từ cửa hàng." + "Element Pro là bắt buộc" "Chúng tớ không thể kết nối với homeserver này. Vui lòng kiểm tra xem cậu đã nhập URL homeserver chính xác chưa. Nếu URL chính xác, hãy liên hệ với quản trị viên homeserver để được hỗ trợ thêm." "Máy chủ không khả dụng do sự cố trong tệp .well-known: %1$s" + "Nhà cung cấp tài khoản đã chọn không hỗ trợ đồng bộ sliding. Cần nâng cấp máy chủ để sử dụng %1$s ." + "%1$s không được phép kết nối với %2$s ." + "Ứng dụng này đã được cấu hình để cho phép: %1$s ." + "Không cho phép nhà cung cấp tài khoản %1$s." "URL homeserver" "Địa chỉ máy chủ của bạn là gì?" "Chọn máy chủ của bạn" diff --git a/features/login/impl/src/main/res/values-zh-rTW/translations.xml b/features/login/impl/src/main/res/values-zh-rTW/translations.xml index 1b0b94d7a6..7170288c5d 100644 --- a/features/login/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/login/impl/src/main/res/values-zh-rTW/translations.xml @@ -37,11 +37,20 @@ "Matrix 是一個開放網路,為了安全且去中心化的通訊而生。" "歡迎回來!" "登入 %1$s" + "開啟 Element Classic" + "在您的裝置上開啟 Element Classic" + "前往「設定」→「安全性與隱私權」" + "在密碼學金鑰管理中,選取加密訊息還原" + "按照說明啟用您的金鑰儲存空間" + "回到 %1$s" + "請先啟用您的金鑰儲存空間,然後再繼續 %1$s" "版本 %1$s" + "檢查帳號" "手動登入" "登入 %1$s" "使用 QR code 登入" "建立帳號" + "歡迎回來" "歡迎使用有史以來最快的 %1$s。速度超快,操作簡便。" "歡迎使用 %1$s。速度超快且簡單。" "Be in your element" @@ -60,6 +69,8 @@ "已取消登入請求" "其他裝置拒絕登入。" "已拒絕登入" + "您不需要進行其他操作。" + "您的其他裝置已登入" "登入已過期。請再試一次。" "未及時完成登入" "您的其他裝置不支援使用 QR cpde 登入 %s。 diff --git a/features/login/impl/src/main/res/values-zh/translations.xml b/features/login/impl/src/main/res/values-zh/translations.xml index fd8105b71e..f9c9141ff2 100644 --- a/features/login/impl/src/main/res/values-zh/translations.xml +++ b/features/login/impl/src/main/res/values-zh/translations.xml @@ -37,11 +37,15 @@ "Matrix 是一个用于安全、去中心化通信的开放网络。" "欢迎回来!" "登录到 %1$s" + "打开 Element Classic" + "在你的设备上打开 Element Classic" + "前往“设置” > “安全与隐私”" "版本%1$s" "手动登录" "登录到 %1$s" "使用二维码登录" "创建账户" + "欢迎回来" "欢迎使用 %1$s,快而简约的消息应用。" "欢迎使用 %1$s,速度与简洁的极致。" "融入您的 Element" diff --git a/features/login/impl/src/main/res/values/localazy.xml b/features/login/impl/src/main/res/values/localazy.xml index b4dee32721..dce4f1a77b 100644 --- a/features/login/impl/src/main/res/values/localazy.xml +++ b/features/login/impl/src/main/res/values/localazy.xml @@ -40,11 +40,12 @@ "Open Element Classic" "Open Element Classic on your device" "Go to Settings > Security & Privacy" - "In Cryptography keys management, select Encrypted message recovery" + "In Cryptography keys management, select Encrypted messages recovery" "Follow the instructions to enable your key storage" "Come back to %1$s" "Enable your key storage before proceeding to %1$s" "Version %1$s" + "Checking account" "Sign in manually" "Sign in to %1$s" "Sign in with QR code" diff --git a/features/logout/impl/src/main/res/values-de/translations.xml b/features/logout/impl/src/main/res/values-de/translations.xml index 8ebea45c0e..9021aee4da 100644 --- a/features/logout/impl/src/main/res/values-de/translations.xml +++ b/features/logout/impl/src/main/res/values-de/translations.xml @@ -1,18 +1,18 @@ - "Möchtest du dich wirklich abmelden?" - "Abmelden" - "Abmelden" - "Abmelden…" + "Bist du sicher, dass du dieses Gerät entfernen möchtest?" + "Dieses Gerät entfernen" + "Dieses Gerät entfernen" + "Gerät wird entfernt…" "Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten." "Du hast das Backup deaktiviert" "Das Backup deiner Schlüssel lief noch, als du offline gegangen bist. Verbinde dich erneut, damit deine Schlüssel vor dem Abmelden gesichert werden können." "Deine Schlüssel werden noch gesichert" - "Bitte warte, bis dieser Vorgang abgeschlossen ist, bevor du dich abmeldest." + "Bitte warte, bis der Vorgang abgeschlossen ist, bevor du dieses Gerät entfernst." "Deine Schlüssel werden noch gesichert" - "Abmelden" + "Dieses Gerät entfernen" "Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten." - "Wiederherstellung nicht eingerichtet" + "Du bist dabei, den Zugriff auf deine verschlüsselten Chats zu verlieren" "Du bist dabei, dich von deiner letzten Sitzung abzumelden. Wenn du dich jetzt abmeldest, verlierst du möglicherweise den Zugriff auf deine verschlüsselten Nachrichten." - "Hast du deinen Wiederherstellungsschlüssel gespeichert?" + "Stelle sicher, dass du Zugriff auf deinen Wiederherstellungsschlüssel hast, bevor du dieses Gerät entfernst" diff --git a/features/logout/impl/src/main/res/values-et/translations.xml b/features/logout/impl/src/main/res/values-et/translations.xml index 4bdf169576..ee5a2ce9d0 100644 --- a/features/logout/impl/src/main/res/values-et/translations.xml +++ b/features/logout/impl/src/main/res/values-et/translations.xml @@ -1,8 +1,8 @@ "Kas sa oled kindel, et soovid välja logida?" - "Logi välja" - "Logi välja" + "Eemalda see seade" + "Eemalda see seade" "Logime välja…" "Oled oma viimasest seansist välja logimas. Kui logid nüüd välja, kaotad ligipääsu oma krüptitud sõnumitele." "Sa oled varukoopiate tegemise välja lülitanud" @@ -10,7 +10,7 @@ "Sinu krüptovõtmed on veel varundamisel" "Enne väljalogimist palun oota, et pooleliolev toiming lõppeb." "Sinu krüptovõtmed on veel varundamisel" - "Logi välja" + "Eemalda see seade" "Sa oled logimas välja oma viimasest sessioonist. Kui teed seda nüüd, siis kaotad ligipääsu oma krüptitud sõnumitele." "Andmete taastamine on seadistamata" "Sa oled logimas välja oma viimasest sessioonist. Kui teed seda nüüd, siis ilmselt kaotad ligipääsu oma krüptitud sõnumitele." diff --git a/features/logout/impl/src/main/res/values-hr/translations.xml b/features/logout/impl/src/main/res/values-hr/translations.xml index 0a5d583a3c..ec8116a8c5 100644 --- a/features/logout/impl/src/main/res/values-hr/translations.xml +++ b/features/logout/impl/src/main/res/values-hr/translations.xml @@ -1,17 +1,18 @@ - "Jeste li sigurni da se želite odjaviti?" - "Odjava" - "Odjava" - "Odjavljivanje…" - "Odjavit ćete se iz svoje posljednje sesije. Ako se sada odjavite, nećete moći pristupiti svojim šifriranim porukama." - "Isključili ste sigurnosno kopiranje" + "Jeste li sigurni da želite ukloniti ovaj uređaj?" + "Ukloni ovaj uređaj" + "Ukloni ovaj uređaj" + "Uklanjanje uređaja…" + "Ovo je vaš jedini uređaj. Ako ga uklonite, trebat će vam ključ za oporavak kako biste potvrdili svoj digitalni identitet i vratili šifrirane razgovore sljedeći put kada se prijavite." + "Izgubiti ćete pristup svojim šifriranim chatovima" "Vaši su se ključevi još uvijek sigurnosno kopirali kada ste se isključili iz mreže. Ponovno se povežite kako bi se vaši ključevi mogli sigurnosno kopirati prije nego što se odjavite." "Vaši se ključevi još uvijek sigurnosno kopiraju" - "Pričekajte da se to dovrši prije nego što se odjavite." + "Pričekajte da se ovo završi prije uklanjanja ovog uređaja." "Vaši se ključevi još uvijek sigurnosno kopiraju" - "Odjava" - "Odjavit ćete se iz svoje posljednje sesije. Ako se sada odjavite, nećete moći pristupiti svojim šifriranim porukama." - "Oporavak nije postavljen" - "Odjavit ćete se iz svoje posljednje sesije. Ako se sada odjavite, možda nećete moći pristupiti svojim šifriranim porukama." + "Ukloni ovaj uređaj" + "Ovo je vaš jedini uređaj. Ako ga uklonite, trebat će vam ključ za oporavak kako biste potvrdili svoj digitalni identitet i vratili šifrirane razgovore sljedeći put kada se prijavite." + "Izgubit ćete pristup svojim šifriranim chatovima" + "Ovo je vaš jedini uređaj. Ako ga uklonite, trebat će vam ključ za oporavak kako biste potvrdili svoj digitalni identitet i vratili šifrirane razgovore sljedeći put kada se prijavite." + "Prije uklanjanja ovog uređaja provjerite imate li pristup ključu za oporavak" diff --git a/features/logout/impl/src/main/res/values-uz/translations.xml b/features/logout/impl/src/main/res/values-uz/translations.xml index 4d03d9cfa3..a6b46bd5b5 100644 --- a/features/logout/impl/src/main/res/values-uz/translations.xml +++ b/features/logout/impl/src/main/res/values-uz/translations.xml @@ -1,17 +1,18 @@ "Haqiqatan ham tizimdan chiqmoqchimisiz?" - "Tizimdan chiqish" - "Tizimdan chiqish" + "Bu qurilmani olib tashlash" + "Bu qurilmani olib tashlash" "Chiqish…" - "Siz oxirgi sessiyangizdan chiqmoqdasiz. Agar hozir chiqib ketsangiz, shifrlangan xabarlaringizga kira olmaysiz." - "Siz zaxira nusxasini oʻchirdingiz" - "Siz oflayn bo‘lganingizda ham kalitlaringiz zaxiralanish jarayonida edi. Tizimdan chiqishdan oldin kalitlaringizning to‘liq zaxiralanishini ta’minlash uchun qayta ulanishingiz zarur." + "Bu sizning yagona qurilmangiz. Agar uni olib tashlasangiz, keyingi safar hisobingizga kirganingizda raqamli shaxsingizni tasdiqlash va shifrlangan chatlaringizni tiklash uchun zaxira kaliti kerak bo‘ladi." + "Shifrlangan chatlarga ruxsat yopiladi" + "Oflaynga chiqqaningizda kalitlaringiz hali ham zaxiralanayotgan edi. Bu qurilmani olib tashlashdan oldin kalitlaringiz zaxiralanishi uchun qayta ulaning." "Kalitlaringiz hamon zaxiralanmoqda" - "Tizimdan chiqishdan oldin bu jarayon tugashini kuting." + "Bu qurilmani olib tashlashdan oldin uning tugashini kuting." "Kalitlaringiz hamon zaxiralanmoqda" - "Tizimdan chiqish" - "Siz oxirgi sessiyangizdan chiqmoqdasiz. Agar hozir chiqib ketsangiz, shifrlangan xabarlaringizga kira olmaysiz." + "Bu qurilmani olib tashlash" + "Bu sizning yagona qurilmangiz. Agar uni o‘chirsangiz, keyingi safar tizimga kirganingizda raqamli shaxsingizni tasdiqlash va shifrlangan chatlaringizni tiklash uchun tiklash kaliti kerak bo‘ladi." "Qayta tiklash sozlanmagan" - "Siz oxirgi sessiyangizdan chiqmoqdasiz. Agar hozir chiqib ketsangiz, shifrlangan xabarlaringizga kira olmay qolishingiz mumkin." + "Bu sizning yagona qurilmangiz. Agar uni olib tashlasangiz, keyingi safar hisobingizga kirganingizda raqamli shaxsingizni tasdiqlash va shifrlangan chatlaringizni tiklash uchun zaxira kaliti kerak bo‘ladi." + "Bu qurilmani olib tashlashdan oldin zaxira kalitiga ruxsatingiz borligini tekshiring" diff --git a/features/logout/impl/src/main/res/values-zh-rTW/translations.xml b/features/logout/impl/src/main/res/values-zh-rTW/translations.xml index 12d5bc20a6..e2b71b61df 100644 --- a/features/logout/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/logout/impl/src/main/res/values-zh-rTW/translations.xml @@ -1,17 +1,18 @@ - "您確定要登出嗎?" - "登出" - "登出" - "正在登出…" - "您將要登出上一次作業階段。若您現在登出,將會失去對加密訊息的存取權。" - "您已關閉備份" - "當您離線時,您的金鑰仍在備份中。請重新連線才能在您登出前備份金鑰。" + "您確定要移除此裝置嗎?" + "移除此裝置" + "移除此裝置" + "正在移除裝置……" + "這是您唯一的裝置。若您移除它,下次登入時您將需要還原金鑰來確認您的數位身份並還原您的加密聊天。" + "您即將失去對您加密聊天的存取權" + "當您離線時,您的金鑰仍在備份中。請重新連線才能在您移除此裝置前備份金鑰。" "您的金鑰仍在備份中" - "請等待此動作完成後再登出。" + "請等待此動作完成後再移除此裝置。" "您的金鑰仍在備份中" - "登出" - "您將要登出上一次作業階段。若您現在登出,將會失去對加密訊息的存取權。" - "未設定復原金鑰" - "您將要登出上一次作業階段。若您現在登出,將會失去對加密訊息的存取權。" + "移除此裝置" + "這是您唯一的裝置。若您移除它,下此登入時將需要還原金鑰來驗證您的數位身份並還原您的加密聊天。" + "您即將失去對您的加密聊天的存取權" + "這是您唯一的裝置。若您移除它,下此登入時將需要還原金鑰來驗證您的數位身份並還原您的加密聊天。" + "在移除此裝置前,請確保您可存取您的還原金鑰" diff --git a/features/messages/impl/src/main/res/values-de/translations.xml b/features/messages/impl/src/main/res/values-de/translations.xml index 5323e731e9..4848f1f282 100644 --- a/features/messages/impl/src/main/res/values-de/translations.xml +++ b/features/messages/impl/src/main/res/values-de/translations.xml @@ -35,7 +35,7 @@ "Video aufnehmen" "Anhang" "Foto- und Videogalerie" - "Standort" + "Standort teilen" "Umfrage" "Textformatierung" "Der Nachrichtenverlauf ist derzeit nicht verfügbar" diff --git a/features/messages/impl/src/main/res/values-hr/translations.xml b/features/messages/impl/src/main/res/values-hr/translations.xml index 3da55fc4d7..03aeae7a0e 100644 --- a/features/messages/impl/src/main/res/values-hr/translations.xml +++ b/features/messages/impl/src/main/res/values-hr/translations.xml @@ -35,7 +35,7 @@ "Snimi videozapis" "Privitak" "Biblioteka fotografija i videozapisa" - "Lokacija" + "Dijeli lokaciju" "Anketa" "Oblikovanje teksta" "Povijest poruka trenutačno nije dostupna." diff --git a/features/messages/impl/src/main/res/values-vi/translations.xml b/features/messages/impl/src/main/res/values-vi/translations.xml index 81ac0b7b8e..5104cd5a5b 100644 --- a/features/messages/impl/src/main/res/values-vi/translations.xml +++ b/features/messages/impl/src/main/res/values-vi/translations.xml @@ -14,6 +14,7 @@ "Đồ vật" "Mặt cười & mọi người" "Du lịch và địa danh" + "Biểu tượng cảm xúc gần đây" "Biểu tượng" "Xử lý phương tiện tải lên không thành công, vui lòng thử lại." "Không thể tải lên tệp phương tiện. Vui lòng thử lại." @@ -44,6 +45,12 @@ "Thu gọn" "Đã sao chép tin nhắn" "Bạn không có quyền gửi tin nhắn trong phòng này" + + "%1$d thành viên đã phản ứng với %2$s" + + + "Bạn và thành viên %1$d đã phản ứng với%2$s" + "Thu gọn" "Xem thêm" "Mới" diff --git a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml index 321c381359..0eea6e808e 100644 --- a/features/messages/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/messages/impl/src/main/res/values-zh-rTW/translations.xml @@ -35,7 +35,7 @@ "錄影" "附件" "照片與影片庫" - "位置" + "分享位置" "投票" "格式化文字" "目前無法檢視訊息歷史紀錄。" diff --git a/features/poll/api/src/main/res/values-vi/translations.xml b/features/poll/api/src/main/res/values-vi/translations.xml index 21651828df..9c94ec71f6 100644 --- a/features/poll/api/src/main/res/values-vi/translations.xml +++ b/features/poll/api/src/main/res/values-vi/translations.xml @@ -1,5 +1,8 @@ + + "%1$d phần trăm tổng số phiếu bầu" + "Xóa lựa chọn trước đó" "Đây là câu trả lời chiến thắng" diff --git a/features/poll/impl/src/main/res/values-vi/translations.xml b/features/poll/impl/src/main/res/values-vi/translations.xml index dc29666c74..b56fe7039d 100644 --- a/features/poll/impl/src/main/res/values-vi/translations.xml +++ b/features/poll/impl/src/main/res/values-vi/translations.xml @@ -5,6 +5,7 @@ "Ẩn phiếu" "Lựa chọn %1$d" "Các thay đổi của bạn chưa được lưu. Bạn có chắc muốn quay lại không?" + "Tùy chọn xóa %1$s" "Câu hỏi hoặc chủ đề" "Cuộc thăm dò này về vấn đề gì?" "Tạo Cuộc thăm dò ý kiến" 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 db242130ed..9f24244b7e 100644 --- a/features/preferences/impl/src/main/res/values-vi/translations.xml +++ b/features/preferences/impl/src/main/res/values-vi/translations.xml @@ -1,5 +1,7 @@ + "Để đảm bảo bạn không bỏ lỡ bất kỳ cuộc gọi quan trọng nào, vui lòng thay đổi cài đặt để cho phép thông báo toàn màn hình khi điện thoại của bạn bị khóa." + "Nâng cao trải nghiệm cuộc gọi của bạn" "Chọn cách nhận thông báo" "Chế độ nhà phát triển" "Cho phép truy cập vào các tính năng và chức năng dành cho nhà phát triển." @@ -7,6 +9,9 @@ "Đặt địa chỉ máy chủ cuộc gọi tùy chỉnh cho Element." "Địa chỉ URL không hợp lệ. Hãy kiểm tra lại giao thức (http/https) và địa chỉ chính xác." "Labs" + "Tải ảnh và video nhanh hơn và giảm mức sử dụng dữ liệu." + "Tối ưu hóa chất lượng media" + "Nhà cung cấp dịch vụ thông báo" "Tắt trình soạn thảo văn bản nâng cao để nhập Markdown thủ công." "Thông báo đã đọc" "Nếu tắt, thông báo đã đọc của bạn sẽ không được gửi cho ai. Bạn vẫn sẽ nhận được thông báo đã đọc từ người khác." diff --git a/features/rageshake/impl/src/main/res/values-vi/translations.xml b/features/rageshake/impl/src/main/res/values-vi/translations.xml index 5a60edd206..6f53dc65e6 100644 --- a/features/rageshake/impl/src/main/res/values-vi/translations.xml +++ b/features/rageshake/impl/src/main/res/values-vi/translations.xml @@ -10,8 +10,11 @@ "Phần mô tả quá ngắn, vui lòng cung cấp thêm chi tiết về những gì đã xảy ra. Cảm ơn!" "Gửi nhật ký sự cố" "Cho phép ghi nhật ký" + "Tệp nhật ký của bạn quá lớn nên không thể đưa vào báo cáo này, vui lòng gửi chúng cho chúng tôi bằng cách khác." "Gửi ảnh chụp màn hình" "Nhật ký lỗi sẽ được đính kèm với tin nhắn của bạn để đảm bảo mọi thứ hoạt động bình thường. Để gửi tin nhắn mà không có nhật ký lỗi, hãy tắt cài đặt này." "%1$s đã bị lỗi ở lần sử dụng gần nhất. Bạn có muốn chia sẻ báo cáo lỗi với chúng tôi không?" + "Nếu bạn gặp sự cố với thông báo, việc tải lên các quy tắc thông báo có thể giúp chúng tôi xác định nguyên nhân chính. Xin lưu ý rằng các quy tắc này có thể chứa thông tin riêng tư, chẳng hạn như tên hiển thị hoặc từ khóa mà bạn muốn nhận thông báo." + "Cài đặt thông báo" "Xem nhật ký" diff --git a/features/rolesandpermissions/impl/src/main/res/values-uz/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-uz/translations.xml index 566ce7f53c..5e00e72504 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-uz/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-uz/translations.xml @@ -5,7 +5,7 @@ "Sozlamalarni o‘zgartirish" "Xabarlarni olib tashlash" "A\'zo" - "Odamlarni taklif qiling va qo‘shilish so‘rovlarini qabul qiling" + "Odamlarni taklif qiling" "Maydonni boshqarish" "Xonalarni boshqarish" "A’zolarni boshqarish" diff --git a/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml index 5e6c736cbe..314b3ff6c4 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-vi/translations.xml @@ -29,6 +29,9 @@ "Bạn có thay đổi chưa được lưu." "Lưu thay đổi?" "Hiện không có người dùng nào bị cấm." + + "%1$d bị cấm" + "%1$d người" @@ -38,6 +41,9 @@ "Họ có thể tham gia lại phòng này nếu được mời." "Bị cấm" "Thành viên" + + "%1$d được mời" + "Quản trị viên" "Người điều hành" "Thành viên phòng" diff --git a/features/rolesandpermissions/impl/src/main/res/values-zh-rTW/translations.xml b/features/rolesandpermissions/impl/src/main/res/values-zh-rTW/translations.xml index 7bc662e2fc..e9933c4819 100644 --- a/features/rolesandpermissions/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/rolesandpermissions/impl/src/main/res/values-zh-rTW/translations.xml @@ -38,6 +38,9 @@ "您有尚未儲存的變更" "是否儲存變更?" "沒有被封鎖的使用者。" + + "%1$d 個已封鎖" + "檢查拼字或嘗試新搜尋" "找不到「%1$s」" @@ -50,6 +53,9 @@ "從聊天室解除封鎖" "黑名單" "成員" + + "%1$d 個已邀請" + "擱置中" "管理員" "版主" 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 33f686332f..d810ca0919 100644 --- a/features/roomdetails/impl/src/main/res/values-de/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-de/translations.xml @@ -1,5 +1,8 @@ + "Neue Mitglieder sehen den Nachrichtenverlauf nicht" + "Neue Mitglieder sehen den Nachrichtenverlauf" + "Jeder sieht den Nachrichtenverlauf" "Du benötigst eine Chat-Adresse, um den Chat im öffentlichen Verzeichnis sichtbar zu machen." "Chat-Adresse bearbeiten" "Beim Aktualisieren der Benachrichtigungseinstellungen ist ein Fehler aufgetreten." @@ -150,6 +153,7 @@ Wir empfehlen keine Verschlüsselung für Chats zu aktivieren, die jeder finden "Zugang" "Jeder in autorisierten Spaces kann beitreten." "Jeder in %1$s kann beitreten." + "Space Mitglieder" "Spaces werden zur Zeit nicht unterstützt." "Du benötigst eine Chat-Adresse, um den Chat im öffentlichen Verzeichnis sichtbar zu machen." "Adresse" 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 09ec7432df..1bc264ca10 100644 --- a/features/roomdetails/impl/src/main/res/values-hr/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-hr/translations.xml @@ -1,5 +1,8 @@ + "član" + "Novi članovi vide povijest" + "Svatko može vidjeti povijest" "Trebat će vam adresa kako bi bila vidljiva u javnom direktoriju." "Uredi adresu" "Došlo je do pogreške prilikom ažuriranja postavke obavijesti." @@ -134,6 +137,7 @@ "Dodaj adresu" "Svatko tko se nalazi u ovlaštenim prostorima može se pridružiti, ali svi ostali moraju zatražiti pristup." "Svi moraju zatražiti pristup." + "Zatraži pridruživanje" "Svatko u %1$s može se pridružiti, ali svi ostali moraju zatražiti pristup." "Da, omogući šifriranje" "Nakon što se šifriranje za sobu omogući, više se neće moći onemogućiti. Povijest poruka bit će vidljiva samo članovima sobe otkad su pozvani ili otkad su joj se pridružili. @@ -144,13 +148,15 @@ Ne preporučujemo omogućavanje šifriranja za sobe koje svatko može pronaći i "Šifriranje" "Omogući sveobuhvatno šifriranje" "Svatko se može pridružiti." - "Odaberite iz kojih se prostora članovi mogu pridružiti ovoj sobi bez pozivnice. %1$s" + "Bilo tko" + "Odaberite iz kojih se prostora članovi mogu pridružiti ovoj sobi bez pozivnice. %1$s" "Upravljaj prostorima" "Samo pozvane osobe mogu se pridružiti." "Samo s pozivnicom" "Pristup" "Svatko tko se nalazi u ovlaštenim prostorima može se pridružiti." "Svatko u %1$s može se pridružiti." + "Članovi prostora" "Prostori trenutačno nisu podržani" "Trebat će vam adresa kako bi bila vidljiva u javnom direktoriju." "Adresa" 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 cac162cf2b..1b4718ee44 100644 --- a/features/roomdetails/impl/src/main/res/values-uz/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-uz/translations.xml @@ -1,5 +1,8 @@ + "Yangi a’zolar tarixni ko‘rmaydi" + "Yangi a’zolar tarixni ko‘radi" + "Tarixni hamma ko‘rishi mumkin" "Katalogda ko‘rinadigan qilish uchun xona manzili kerak bo‘ladi." "Xona manzili" "Bildirishnoma sozlamalarini yangilashda xatolik yuz berdi." @@ -9,7 +12,7 @@ "Odamlarni taqiqlash" "Xabarlarni olib tashlash" "A\'zo" - "Odamlarni taklif qiling va qo‘shilish so‘rovlarini qabul qiling" + "Odamlarni taklif qiling" "A’zolarni boshqarish" "Xabarlar va kontent" "Moderator" @@ -131,6 +134,7 @@ "Xona manzilini kiritish" "Vakolatli guruhlardagi har kim qo‘shilishi mumkin, lekin qolganlar ruxsat so‘rashi kerak. Tarjima eslatmasi yo‘q" "Xonaga qo‘shilishni istalgan kishi so‘rashi mumkin, lekin administrator yoki moderator so‘rovni qabul qilishi kerak" + "Qo‘shilish uchun so‘rash" "%1$s ichidagi istalgan kishi qo‘shilishi mumkin, lekin qolganlar ruxsat so‘rashi kerak." "Ha, shifrlashni yoqish" "Yoqilgandan so‘ng, xona uchun shifrlashni o‘chirib bo‘lmaydi. Xabarlar tarixi faqat xona a’zolari taklif qilinganidan yoki xonaga qo‘shilganidan keyingi davrdan boshlab ko‘rinadi. Xona a’zolaridan tashqari hech kim xabarlarni o‘qiy olmaydi. Bu botlar va ko‘priklarning to‘g‘ri ishlashiga to‘sqinlik qilishi mumkin. @@ -140,6 +144,7 @@ Shu sababli, har kim topishi va qo‘shilishi mumkin bo‘lgan xonalar uchun shi "Shifrlash" "End-to-end shifrlashni yoqish" "Istalgan kishi topishi va qo‘shilishi mumkin" + "Har kim" "Qaysi maydonlar a’zolari bu xonaga taklifnomalarsiz kirishi mumkinligini tanlang. %1$s" "Maydonlarni boshqarish" "Odamlar faqat taklif qilingan taqdirdagina qo‘shilishi mumkin" @@ -147,15 +152,18 @@ Shu sababli, har kim topishi va qo‘shilishi mumkin bo‘lgan xonalar uchun shi "Xonaga kirish huquqi" "Ruxsat berilgan maydonlardagi istalgan kishi qo‘shilishi mumkin." "%1$s ichidagi istalgan kishi qo‘shilishi mumkin." + "Maydon a’zolari" "Hozirda maydonlar qo‘llab-quvvatlanmaydi" "Katalogda ko‘rinadigan qilish uchun xona manzili kerak bo‘ladi." "Manzil" "Bu xonani %1$s umumiy xonalar ro‘yxatidan qidirib topish imkoniyatini berish" "Umumiy katalogni qidirish orqali topishga ruxsat bering." "Umumiy xona ro‘yxatida ko‘rinadi" + "Har kim (tarix hammaga ochiq)" + "O‘zgarishlar avvalgi xabarlarga ta’sir qilmaydi, faqat yangilariga ta’sir qiladi.%1$s" "Tarixni kim o‘qiy oladi" - "Taklif qilinganidan buyon faqat a’zolar" - "A’zolar faqat bu parametr tanlanganidan keyin" + "Taklif qilinganidan beri a’zo" + "A’zolar (to‘liq tarix)" "Xona manzillari xonalarni topish va ularga kirish usullaridir. Bu shuningdek xonangizni boshqalar bilan oson ulashish imkonini beradi. Xonangizni o‘z homeserveringizning ommaviy xonalar ro‘yxatida e’lon qilishni tanlashingiz mumkin." "xona nashriyoti" 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 a2ee35b563..ac37e6fcfa 100644 --- a/features/roomdetails/impl/src/main/res/values-vi/translations.xml +++ b/features/roomdetails/impl/src/main/res/values-vi/translations.xml @@ -36,6 +36,7 @@ "Bạn có thay đổi chưa được lưu." "Lưu thay đổi?" "Thêm chủ đề" + "Phòng công cộng" "Chỉnh sửa thông tin" "Có lỗi không xác định, thông tin không được cập nhật." "Không thể cập nhật phòng" @@ -58,6 +59,9 @@ "Chủ đề" "Đang cập nhật thông tin…" "Hiện không có người dùng nào bị cấm." + + "%1$d bị cấm" + "%1$d người" @@ -67,6 +71,9 @@ "Họ có thể tham gia lại phòng này nếu được mời." "Bị cấm" "Thành viên" + + "%1$d được mời" + "Quản trị viên" "Người điều hành" "Thành viên phòng" 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 2b784b91ea..1cbabe0e54 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 @@ -1,5 +1,8 @@ + "新成員無法檢視歷史" + "新成員可以檢視歷史" + "任何人都可以檢視歷史" "您需要地址才能在公開目錄中顯示。" "編輯地址" "更新通知設定時發生錯誤。" @@ -63,6 +66,7 @@ "個人檔案" "請求加入" "角色與權限" + "名稱" "安全與隱私" "安全性" "分享聊天室" @@ -70,6 +74,9 @@ "主題" "正在更新聊天室…" "沒有被封鎖的使用者。" + + "%1$d 個已封鎖" + "檢查拼字或嘗試新搜尋" "找不到「%1$s」" @@ -82,6 +89,9 @@ "從聊天室解除封鎖" "黑名單" "成員" + + "%1$d 個已邀請" + "擱置中" "管理員" "版主" @@ -119,8 +129,10 @@ "聊天室資訊" "角色與權限" "新增地址" + "任何在授權空間的人都可以加入,但其他人都必須提出申請。" "所有人都必須申請存取權。" "要求加入" + "任何在 %1$s 中的人都可以加入,但其他人都必須提出申請。" "是的,啟用加密" "啟用後就無法停用聊天室的加密,只有受邀的聊天室成員或加入聊天室後才能看到訊息歷史紀錄。 除了聊天室成員以外,任何人都不能讀取訊息。這可能會讓機器人與橋接無法正常運作。 @@ -131,22 +143,29 @@ "啟用端到端加密" "任何人都可以加入。" "任何人" + "選擇哪些空間的成員不需要邀請就可以加入此聊天室。%1$s" + "管理空間" "僅受邀者才能加入。" "僅限邀請" "存取權" + "任何位於已授權空間的人都可以加入。" + "任何在 %1$s 中的人都可以加入。" + "空間成員" "目前不支援空間" "您需要地址才能在公開目錄中顯示。" "地址" "允許透過搜尋 %1$s 公開聊天室目錄找到此聊天室" "允許其他人透過公開目錄找到。" "在公開目錄中可見" - "任何人" + "任何人(歷史紀錄公開)" + "變更不會影響先前的訊息,只會影響新訊息。%1$s" "誰可以讀取歷史紀錄" - "僅在成員被邀請後" - "選取此選項後僅限成員" + "成員,邀請後" + "成員(完整歷史)" "聊天室地址是尋找與存取聊天室的方法。也確保您可以輕鬆與其他人分享聊天室。 您可以選擇在家伺服器公開聊天室目錄中發佈您的聊天室。" "聊天室發佈" + "地址是尋找與存取聊天室與空間的一種方式。這也讓您可以輕鬆地與其他人分享這些資訊。" "能見度" "安全與隱私" diff --git a/features/securebackup/impl/src/main/res/values-de/translations.xml b/features/securebackup/impl/src/main/res/values-de/translations.xml index 84140d4da0..8363cb9754 100644 --- a/features/securebackup/impl/src/main/res/values-de/translations.xml +++ b/features/securebackup/impl/src/main/res/values-de/translations.xml @@ -11,7 +11,7 @@ "Stelle deine kryptographische Identität und deinen Nachrichtenverlauf mit einem Wiederherstellungsschlüssel wieder her, falls du deine Geräte verloren hast." "Wiederherstellungsschlüssel eingeben" "Dein Schlüssel ist derzeit nicht synchronisiert." - "Wiederherstellung einrichten" + "Wiederherstellungsschlüssel einrichten" "Öffne " "%1$s" @@ -32,8 +32,8 @@ "Deine Kontodaten, Kontakte, Einstellungen und die Liste der Chats bleiben erhalten" "Du verlierst alle bisherigen Nachrichten, wenn sie ausschließlich auf dem Server gespeichert sein sollten." "Du musst alle deine bestehenden Geräte und Kontakte erneut verifizieren." - "Setze deine Identität nur dann zurück, wenn du keinen Zugriff mehr auf ein anderes angemeldetes Gerät hast und auch deinen Wiederherstellungsschlüssel verloren hast." - "Bestätigung unmöglich? Dann musst du deine Identität zurücksetzen." + "Setze deine digitale Identität nur dann zurück, wenn du keinen Zugriff auf ein anderes verifiziertes Gerät hast und deinen Wiederherstellungsschlüssel verloren hast." + "Bestätigung nicht möglich? Setze deine digitale Identität zurück." "Ausschalten" "Du verlierst deine verschlüsselten Nachrichten, wenn du auf allen Geräten abgemeldet bist." "Bist du sicher, dass du das Backup deaktivieren willst?" @@ -67,12 +67,12 @@ "Wiederherstellungsschlüssel erstellen" "Teile das mit niemandem!" "Einrichtung der Wiederherstellung erfolgreich" - "Wiederherstellung einrichten" + "Wiederherstellungsschlüssel einrichten" "Ja, zurücksetzen" "Das Zurücksetzen kann nicht rückgängig gemacht werden." - "Bist du sicher, dass du deine Identität zurücksetzen möchtest?" + "Bist du sicher, dass du deine digitale Identität zurücksetzen möchtest?" "Es ist ein unbekannter Fehler aufgetreten. Bitte überprüfe das Passwort deines Kontos und versuche es erneut." "Eingeben…" - "Bestätige, dass du deine Identität zurücksetzen möchtest." + "Bestätige, dass du deine digitale Identität zurücksetzen möchtest." "Gib dein Passwort ein, um fortzufahren" diff --git a/features/securebackup/impl/src/main/res/values-hr/translations.xml b/features/securebackup/impl/src/main/res/values-hr/translations.xml index 3f146d279f..9c470b8895 100644 --- a/features/securebackup/impl/src/main/res/values-hr/translations.xml +++ b/features/securebackup/impl/src/main/res/values-hr/translations.xml @@ -2,16 +2,17 @@ "Brisanje pohrane ključeva" "Uključivanje sigurnosnog kopiranja" - "Sigurno pohranite svoj kriptografski identitet i ključeve poruka na poslužitelju. To će vam omogućiti pregled povijesti poruka na svim novim uređajima. %1$s." + "To će vam omogućiti pregled povijesti razgovora na svim novim uređajima i potrebno je za sigurnosnu kopiju razgovora i digitalnog identiteta. %1$s ." "Pohrana ključeva" "Za postavljanje oporavka mora biti uključena pohrana ključeva." "Prenesi ključeve s ovog uređaja" "Dopusti pohranu ključeva" "Promjena ključa za oporavak" - "Ako ste izgubili sve postojeće uređaje, oporavite svoj kriptografski identitet i povijest poruka pomoću ključa za oporavak." + "Vaši se razgovori automatski sigurnosno kopiraju enkripcijom od početka do kraja. Da biste vratili ovu sigurnosnu kopiju i zadržali svoj digitalni identitet kada izgubite pristup svim svojim uređajima, trebat će vam ključ za oporavak." "Unesi ključ za oporavak" "Vaša pohrana ključeva trenutačno nije sinkronizirana." - "Postavljanje oporavka" + "ključ za oporavak" + "Vaši se razgovori automatski sigurnosno kopiraju enkripcijom od početka do kraja. Da biste vratili ovu sigurnosnu kopiju i zadržali svoj digitalni identitet kada izgubite pristup svim svojim uređajima, trebat će vam ključ za oporavak." "Otvorite %1$s na stolnom uređaju" "Ponovno se prijavite na svoj račun" "Kada se od vas zatraži da potvrdite svoj uređaj, odaberite %1$s" @@ -24,9 +25,9 @@ "Izgubit ćete svu povijest poruka koja je pohranjena samo na poslužitelju" "Morat ćete ponovno potvrditi sve svoje postojeće uređaje i kontakte" "Poništite svoj identitet samo ako nemate pristup drugom prijavljenom uređaju i ako ste izgubili ključ za oporavak." - "Ne možete potvrditi? Morat ćete poništiti svoj identitet." - "Isključi" - "Izgubit ćete šifrirane poruke ako se odjavite sa svih uređaja." + "Ne možete potvrditi? Morat ćete resetirati svoj digitalni identitet." + "Izbriši" + "Izgubit ćete svoju šifriranu povijest razgovora i morat ćete resetirati svoj digitalni identitet ako uklonite sve svoje uređaje." "Jeste li sigurni da želite isključiti sigurnosno kopiranje?" "Brisanjem pohrane ključeva uklonit ćete svoj kriptografski identitet i ključeve poruka s poslužitelja te isključiti sljedeće sigurnosne značajke:" "Na novim uređajima nećete imati šifriranu povijest poruka" @@ -58,12 +59,12 @@ "Generirajte svoj ključ za oporavak" "Ne dijelite ovo ni s kim!" "Postavljanje oporavka je uspjelo" - "Postavljanje oporavka" + "ključ za oporavak" "Da, poništi sada" "Ovaj je proces nepovratan." - "Jeste li sigurni da želite poništiti svoj identitet?" + "Jeste li sigurni da želite resetirati svoj digitalni identitet?" "Došlo je do nepoznate pogreške. Provjerite je li zaporka vašeg računa ispravna i pokušajte ponovno." "Unos…" - "Potvrdite da želite poništiti svoj identitet." + "Potvrdite da želite resetirati svoj digitalni identitet." "Unesite zaporku računa kako biste nastavili" diff --git a/features/securebackup/impl/src/main/res/values-ru/translations.xml b/features/securebackup/impl/src/main/res/values-ru/translations.xml index ec5237235e..ef80347ea4 100644 --- a/features/securebackup/impl/src/main/res/values-ru/translations.xml +++ b/features/securebackup/impl/src/main/res/values-ru/translations.xml @@ -19,7 +19,7 @@ "«Сбросить все»" "Следуйте инструкциям, чтобы создать новый ключ восстановления" "Сохраните новый ключ восстановления в менеджере паролей или зашифрованной заметке" - "Сбросьте шифрование вашего аккаунта, используя другое устройство" + "Сбросьте шифрование Вашего аккаунта, используя другое устройство" "Продолжить сброс" "Данные вашего аккаунта, контакты, настройки и список чатов будут сохранены" "Вы потеряете историю тех сообщений, которые хранятся только на сервере" diff --git a/features/securebackup/impl/src/main/res/values-uz/translations.xml b/features/securebackup/impl/src/main/res/values-uz/translations.xml index 9e90d2f441..3a93e264dd 100644 --- a/features/securebackup/impl/src/main/res/values-uz/translations.xml +++ b/features/securebackup/impl/src/main/res/values-uz/translations.xml @@ -2,16 +2,17 @@ "Zaxiralashni o\'chirib qo\'ying" "Zaxiralashni yoqing" - "Kryptografik shaxsiyatingizni va xabar kalitlaringizni serverda xavfsiz saqlang. Bu sizga har qanday yangi qurilmalarda xabar tarixingizni ko\'rish imkonini beradi. %1$s." + "Bu sizga chat tarixingizni har qanday yangi qurilmalarda ko‘rish imkonini beradi hamda chatlar zaxirasi va raqamli identifikatsiya uchun talab qilinadi. %1$s." "Kalitlar ombori" - "Tiklashni sozlash uchun kalitlar xotirasini yoqish kerak." + "Chatlarni zaxiralash uchun kalit xotirasi yoqilishi kerak." "Bu qurilmadan kalitlarni yuklash" "Kalit saqlashga ruxsat berish" "Qayta tiklash kalitini o\'zgartiring" - "Agar barcha mavjud qurilmalaringizni yoʻqotgan boʻlsangiz, tiklash kaliti yordamida kriptografik shaxsingizni va xabarlar tarixingizni qayta tiklang." + "Chatlaringiz avtomatik ravishda boshidan oxirigacha shifrlash bilan zaxiralanadi. Bu zaxirani tiklash va barcha qurilmalaringizdan foydalana olmay qolganingizda raqamli identifikatoringizni saqlab qolish uchun sizga tiklash kaliti kerak bo‘ladi." "Tiklash kalitini kiriting" "Kalit xotirasi hozirda sinxronlanmagan." "Qayta tiklashni sozlang" + "Chatlaringiz avtomatik ravishda boshidan oxirigacha shifrlash bilan zaxiralanadi. Bu zaxirani tiklash va barcha qurilmalaringizdan foydalana olmay qolganingizda raqamli identifikatoringizni saqlab qolish uchun sizga tiklash kaliti kerak bo‘ladi." "%1$s ni kompyuterda oching" "Hisobingizga qaytadan kiring" "Qurilmangizni tasdiqlash soʻralganda, %1$s ni tanlang" @@ -23,12 +24,12 @@ "Hisob maʼlumotlaringiz, kontaktlaringiz, sozlamalaringiz va suhbatlar roʻyxatingiz saqlanib qoladi" "Faqat serverda saqlangan har qanday xabarlar tarixi oʻchib ketadi" "Barcha mavjud qurilma va kontaktlarni qayta tasdiqlashingiz kerak boʻladi" - "Agar boshqa hisobga kirilgan qurilmaga kira olmasangiz va tiklash kaliti yo‘qolgan bo‘lsa, shaxsingizni tiklang." - "Tasdiqlanmadimi? Shaxsingizni tiklashingiz kerak." + "Agar boshqa tasdiqlangan qurilmaga kira olmasangiz va zaxira kalitingiz bo‘lmasa, raqamli identifikatoringizni asliga qaytaring." + "Tasdiqlay olmayapsizmi? Raqamli identifikatoringizni asliga qaytarishingiz kerak." "O\'chirish" - "Agar barcha qurilmalardan chiqqan boʻlsangiz, shifrlangan xabarlaringizni yoʻqotasiz." - "Haqiqatan ham zaxiralashni o‘chirib qo‘ymoqchimisiz?" - "Zaxiralashni o‘chirib qo‘ysangiz, joriy shifrlash kaliti zaxira nusxasi o‘chiriladi va boshqa xavfsizlik funksiyalari o‘chiriladi. Bunday holda siz:" + "Agar barcha qurilmalaringizni olib tashlasangiz, shifrlangan chat tarixingizni yo‘qotasiz va raqamli identifikatoringizni asliga qaytarishingiz kerak bo‘ladi." + "Kalitlar omborini o‘chirib tashlashni xohlaysizmi?" + "Kalit xotirasini o‘chirish raqamli identifikatsiya va xabar kalitlaringizni serverdan olib tashlaydi hamda quyidagi xavfsizlik funksiyalarini faolsizlantiradi:" "Yangi qurilmalarda shifrlangan xabarlar tarixi mavjud emas" "Agar tizimdan chiqqan boʻlsangiz, shifrlangan xabarlaringizga kirish huquqini yoʻqotasiz%1$s hamma joyda" "Haqiqatan ham zaxiralashni o‘chirib qo‘ymoqchimisiz?" @@ -61,9 +62,9 @@ "Qayta tiklashni sozlang" "Ha, hozir asliga qaytarish" "Bu jarayonni ortga qaytarib boʻlmaydi." - "Haqiqatan ham shaxsingizni qayta tiklamoqchimisiz?" + "Haqiqatan ham raqamli identifikatoringizni tiklamoqchimisiz?" "Noma’lum xato yuz berdi. Iltimos, hisobingiz parolining to‘g‘riligini tekshiring va qaytadan urinib ko‘ring." "Kirish…" - "Shaxsingizni tiklashni tasdiqlang." + "Raqamli identifikatoringizni asliga qaytarmoqchi ekaningizni tasdiqlang." "Davom etish uchun hisobingiz parolini kiriting" diff --git a/features/securebackup/impl/src/main/res/values-vi/translations.xml b/features/securebackup/impl/src/main/res/values-vi/translations.xml index 70913a5e24..74784f8921 100644 --- a/features/securebackup/impl/src/main/res/values-vi/translations.xml +++ b/features/securebackup/impl/src/main/res/values-vi/translations.xml @@ -4,10 +4,28 @@ "Bật tính năng sao lưu" "Điều này cho phép bạn xem lịch sử trò chuyện trên bất kỳ thiết bị mới nào và cần thiết để sao lưu trò chuyện cũng như danh tính kỹ thuật số. %1$s." "Lưu trữ khóa" + "Bạn cần bật tính năng lưu trữ khóa để sao lưu các cuộc trò chuyện của mình." + "Tải lên các khóa từ thiết bị này" + "Cho phép lưu trữ khóa" "Thay đổi khóa khôi phục." + "Các cuộc trò chuyện của bạn được tự động sao lưu bằng mã hóa đầu cuối. Để khôi phục bản sao lưu này và giữ lại danh tính kỹ thuật số của bạn khi bạn mất quyền truy cập vào tất cả các thiết bị, bạn sẽ cần khóa khôi phục." "Nhập mã khôi phục." "Kho lưu trữ khóa của bạn hiện đang không đồng bộ." "Lấy khóa khôi phục." + "Các cuộc trò chuyện của bạn được tự động sao lưu bằng mã hóa đầu cuối. Để khôi phục bản sao lưu này và giữ lại danh tính kỹ thuật số của bạn khi bạn mất quyền truy cập vào tất cả các thiết bị, bạn sẽ cần khóa khôi phục." + "Mở %1$s trên máy tính để bàn" + "Đăng nhập lại vào tài khoản của bạn" + "Khi được yêu cầu xác minh thiết bị của bạn, chọn %1$s" + "“Khôi phục tất cả”" + "Hãy làm theo hướng dẫn để tạo khóa khôi phục mới." + "Hãy lưu khóa khôi phục mới của bạn vào trình quản lý mật khẩu hoặc ghi chú được mã hóa." + "Đặt lại mã hóa cho tài khoản của bạn bằng một thiết bị khác." + "Tiếp tục đặt lại" + "Thông tin tài khoản, danh bạ, tùy chọn và danh sách trò chuyện của bạn sẽ được lưu giữ." + "Bạn sẽ mất toàn bộ lịch sử tin nhắn chỉ được lưu trữ trên máy chủ." + "Bạn sẽ cần xác minh lại tất cả các thiết bị và danh bạ hiện có của mình." + "Chỉ nên đặt lại danh tính kỹ thuật số của bạn nếu bạn không có quyền truy cập vào thiết bị đã được xác minh khác và bạn không có khóa khôi phục." + "Không thể xác nhận? Bạn cần phải thiết lập lại danh tính kỹ thuật số của mình." "Xoá" "Bạn sẽ mất các tin nhắn đã mã hóa nếu bạn đăng xuất khỏi tất cả các thiết bị." "Bạn có chắc muốn xóa lưu trữ khóa không?" diff --git a/features/securebackup/impl/src/main/res/values-zh-rTW/translations.xml b/features/securebackup/impl/src/main/res/values-zh-rTW/translations.xml index 85061fe044..9b791eb938 100644 --- a/features/securebackup/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/securebackup/impl/src/main/res/values-zh-rTW/translations.xml @@ -2,16 +2,17 @@ "關閉備份功能" "開啟備份功能" - "在伺服器上安全地儲存您的密碼學身份與訊息金鑰。這將讓您可以在任何新裝置上檢視訊息歷史紀錄。%1$s" + "此舉將讓您能在任何新裝置上檢視聊天記錄,且對於備份聊天內容及數位身分而言是必要的。%1$s。" "金鑰儲存空間" - "必須開啟金鑰儲存空間才能設定復原。" + "必須開啟金鑰儲存空間才能備份您的聊天。" "從此裝置上傳金鑰" "允許金鑰儲存空間" "變更復原金鑰" - "若您遺失了您現有的所有裝置,請使用復原金鑰來還原您的密碼學身份與訊息歷史紀錄。" + "您的聊天會自動以端到端加密方式進行備份。若您無法存取所有裝置,欲還原此備份並保留您的數位身分,您將需要使用還原金鑰。" "輸入復原金鑰" "您的金鑰儲存空間目前並未同步。" - "設定復原" + "取得還原金鑰" + "您的聊天會自動使用端到端加密備份。若您失去對您所有裝置的存取權,且要還原此備份並保留您的數位身份的話,您就會需要您的還原金鑰。" "在桌上型裝置中開啟 %1$s" "再次登入您的帳號" "當要求驗證您的裝置時,請選取 %1$s" @@ -23,12 +24,12 @@ "您的帳號詳細資訊、聯絡人、偏好設定與聊天清單都會保留" "您將會遺失僅儲存在伺服器上的任何訊息歷史紀錄" "您將需要再次驗證所有現有裝置與聯絡人" - "僅當您無法存取其他已登入裝置且遺失復原金鑰時才重設您的身份。" - "無法確認?您需要重設身份。" - "關閉" - "若您登出所有裝置,您將失去加密訊息。" - "您確定您要關閉備份嗎?" - "刪除金鑰儲存空間會從伺服器移除您的密碼學身份與訊息金鑰,並關閉以下安全性功能:" + "僅當您無法存取其他已驗證的裝置且沒有還原金鑰時才重設您的數位身份。" + "無法確認?您需要重設數位身份。" + "刪除" + "若您移除所有裝置,您將遺失加密的聊天記錄,並需重設您的數位身分。" + "您確定您要刪除金鑰儲存空間嗎?" + "刪除金鑰儲存空間會從伺服器移除您的數位身份與訊息金鑰,並關閉以下安全性功能:" "您將無法在新裝置上存取加密訊息歷史紀錄" "若您徹底登出 %1$s,您將無法存取加密訊息" "您確定要關閉金鑰儲存空間並刪除它嗎?" @@ -58,12 +59,12 @@ "產生您的復原金鑰" "不要與任何人分享!" "復原設定成功" - "設定復原" + "取得還原金鑰" "是的,立刻重設" "此過程不可逆。" "您確定您想要重設您的身份嗎?" "發生了未知錯誤。請檢查您帳號的密碼是否正確,然後再試一次。" "輸入……" - "確認您要重設您的身份。" + "確認您要重設您的數位身份。" "輸入您帳號的密碼以繼續" diff --git a/features/securityandprivacy/impl/src/main/res/values-de/translations.xml b/features/securityandprivacy/impl/src/main/res/values-de/translations.xml index 0bc6aa8877..c60efc009c 100644 --- a/features/securityandprivacy/impl/src/main/res/values-de/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-de/translations.xml @@ -29,6 +29,7 @@ Wir empfehlen keine Verschlüsselung für Chats zu aktivieren, die jeder finden "Zugang" "Jeder in autorisierten Spaces kann beitreten." "Jeder in %1$s kann beitreten." + "Space Mitglieder" "Spaces werden zur Zeit nicht unterstützt." "Du benötigst eine Chat-Adresse, um den Chat im öffentlichen Verzeichnis sichtbar zu machen." "Adresse" diff --git a/features/securityandprivacy/impl/src/main/res/values-hr/translations.xml b/features/securityandprivacy/impl/src/main/res/values-hr/translations.xml index 3dd3e7468d..4038a7a412 100644 --- a/features/securityandprivacy/impl/src/main/res/values-hr/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-hr/translations.xml @@ -10,6 +10,7 @@ "Dodaj adresu" "Svatko tko se nalazi u ovlaštenim prostorima može se pridružiti, ali svi ostali moraju zatražiti pristup." "Svi moraju zatražiti pristup." + "Zatraži pridruživanje" "Svatko u %1$s može se pridružiti, ali svi ostali moraju zatražiti pristup." "Da, omogući šifriranje" "Nakon što se šifriranje za sobu omogući, više se neće moći onemogućiti. Povijest poruka bit će vidljiva samo članovima sobe otkad su pozvani ili otkad su joj se pridružili. @@ -20,13 +21,15 @@ Ne preporučujemo omogućavanje šifriranja za sobe koje svatko može pronaći i "Šifriranje" "Omogući sveobuhvatno šifriranje" "Svatko se može pridružiti." - "Odaberite iz kojih se prostora članovi mogu pridružiti ovoj sobi bez pozivnice. %1$s" + "Bilo tko" + "Odaberite iz kojih se prostora članovi mogu pridružiti ovoj sobi bez pozivnice. %1$s" "Upravljaj prostorima" "Samo pozvane osobe mogu se pridružiti." "Samo s pozivnicom" "Pristup" "Svatko tko se nalazi u ovlaštenim prostorima može se pridružiti." "Svatko u %1$s može se pridružiti." + "Članovi prostora" "Prostori trenutačno nisu podržani" "Trebat će vam adresa kako bi bila vidljiva u javnom direktoriju." "Adresa" diff --git a/features/securityandprivacy/impl/src/main/res/values-uz/translations.xml b/features/securityandprivacy/impl/src/main/res/values-uz/translations.xml index 2197e52905..134378f4f5 100644 --- a/features/securityandprivacy/impl/src/main/res/values-uz/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-uz/translations.xml @@ -10,6 +10,7 @@ "Xona manzilini kiritish" "Vakolatli guruhlardagi har kim qo‘shilishi mumkin, lekin qolganlar ruxsat so‘rashi kerak. Tarjima eslatmasi yo‘q" "Xonaga qo‘shilishni istalgan kishi so‘rashi mumkin, lekin administrator yoki moderator so‘rovni qabul qilishi kerak" + "Qo‘shilish uchun so‘rash" "%1$s ichidagi istalgan kishi qo‘shilishi mumkin, lekin qolganlar ruxsat so‘rashi kerak." "Ha, shifrlashni yoqish" "Yoqilgandan so‘ng, xona uchun shifrlashni o‘chirib bo‘lmaydi. Xabarlar tarixi faqat xona a’zolari taklif qilinganidan yoki xonaga qo‘shilganidan keyingi davrdan boshlab ko‘rinadi. Xona a’zolaridan tashqari hech kim xabarlarni o‘qiy olmaydi. Bu botlar va ko‘priklarning to‘g‘ri ishlashiga to‘sqinlik qilishi mumkin. @@ -19,6 +20,7 @@ Shu sababli, har kim topishi va qo‘shilishi mumkin bo‘lgan xonalar uchun shi "Shifrlash" "End-to-end shifrlashni yoqish" "Istalgan kishi topishi va qo‘shilishi mumkin" + "Har kim" "Qaysi maydonlar a’zolari bu xonaga taklifnomalarsiz kirishi mumkinligini tanlang. %1$s" "Maydonlarni boshqarish" "Odamlar faqat taklif qilingan taqdirdagina qo‘shilishi mumkin" @@ -26,15 +28,18 @@ Shu sababli, har kim topishi va qo‘shilishi mumkin bo‘lgan xonalar uchun shi "Xonaga kirish huquqi" "Ruxsat berilgan maydonlardagi istalgan kishi qo‘shilishi mumkin." "%1$s ichidagi istalgan kishi qo‘shilishi mumkin." + "Maydon a’zolari" "Hozirda maydonlar qo‘llab-quvvatlanmaydi" "Katalogda ko‘rinadigan qilish uchun xona manzili kerak bo‘ladi." "Manzil" "Bu xonani %1$s umumiy xonalar ro‘yxatidan qidirib topish imkoniyatini berish" "Umumiy katalogni qidirish orqali topishga ruxsat bering." "Umumiy xona ro‘yxatida ko‘rinadi" + "Har kim (tarix hammaga ochiq)" + "O‘zgarishlar avvalgi xabarlarga ta’sir qilmaydi, faqat yangilariga ta’sir qiladi.%1$s" "Tarixni kim o‘qiy oladi" - "Taklif qilinganidan buyon faqat a’zolar" - "A’zolar faqat bu parametr tanlanganidan keyin" + "Taklif qilinganidan beri a’zo" + "A’zolar (to‘liq tarix)" "Xona manzillari xonalarni topish va ularga kirish usullaridir. Bu shuningdek xonangizni boshqalar bilan oson ulashish imkonini beradi. Xonangizni o‘z homeserveringizning ommaviy xonalar ro‘yxatida e’lon qilishni tanlashingiz mumkin." "xona nashriyoti" diff --git a/features/securityandprivacy/impl/src/main/res/values-zh-rTW/translations.xml b/features/securityandprivacy/impl/src/main/res/values-zh-rTW/translations.xml index b9a93922f4..5239585201 100644 --- a/features/securityandprivacy/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/securityandprivacy/impl/src/main/res/values-zh-rTW/translations.xml @@ -2,9 +2,16 @@ "您需要地址才能在公開目錄中顯示。" "編輯地址" + "在此空間中,成員可無須邀請直接加入聊天室。" + "管理空間" + "(未知空間)" + "您尚非成員的其他空間" + "您的空間" "新增地址" + "任何在授權空間的人都可以加入,但其他人都必須提出申請。" "所有人都必須申請存取權。" "要求加入" + "任何在 %1$s 中的人都可以加入,但其他人都必須提出申請。" "是的,啟用加密" "啟用後就無法停用聊天室的加密,只有受邀的聊天室成員或加入聊天室後才能看到訊息歷史紀錄。 除了聊天室成員以外,任何人都不能讀取訊息。這可能會讓機器人與橋接無法正常運作。 @@ -15,22 +22,29 @@ "啟用端到端加密" "任何人都可以加入。" "任何人" + "選擇哪些空間的成員不需要邀請就可以加入此聊天室。%1$s" + "管理空間" "僅受邀者才能加入。" "僅限邀請" "存取權" + "任何位於已授權空間的人都可以加入。" + "任何在 %1$s 中的人都可以加入。" + "空間成員" "目前不支援空間" "您需要地址才能在公開目錄中顯示。" "地址" "允許透過搜尋 %1$s 公開聊天室目錄找到此聊天室" "允許其他人透過公開目錄找到。" "在公開目錄中可見" - "任何人" + "任何人(歷史紀錄公開)" + "變更不會影響先前的訊息,只會影響新訊息。%1$s" "誰可以讀取歷史紀錄" - "僅在成員被邀請後" - "選取此選項後僅限成員" + "成員,邀請後" + "成員(完整歷史)" "聊天室地址是尋找與存取聊天室的方法。也確保您可以輕鬆與其他人分享聊天室。 您可以選擇在家伺服器公開聊天室目錄中發佈您的聊天室。" "聊天室發佈" + "地址是尋找與存取聊天室與空間的一種方式。這也讓您可以輕鬆地與其他人分享這些資訊。" "能見度" "安全與隱私" diff --git a/features/space/impl/src/main/res/values-de/translations.xml b/features/space/impl/src/main/res/values-de/translations.xml index bc1e4265b6..6dee82123f 100644 --- a/features/space/impl/src/main/res/values-de/translations.xml +++ b/features/space/impl/src/main/res/values-de/translations.xml @@ -8,9 +8,11 @@ "Dadurch wirst du auch aus allen Chats in diesem Space entfernt." "Du musst einen anderen Admin für diesen Space zuweisen, bevor du ihn verlassen kannst." + "Du bist der einzige Eigentümer von %1$s. Du musst die Eigentumsrechte an jemand anderen übertragen, bevor du den Space verlässt." "Du wirst aus den folgenden Chats nicht entfernt, weil du der einzige Admin bist:" "%1$s verlassen?" "Du bist der einzige Administrator für %1$s" + "Eigentumsrechte übertragen" "Chat" "Das Hinzufügen eines Chats hat keinen Einfluss auf die Beitrittsregeln. Um die Regeln zu ändern, gehe zu \"Raum Info\" und dann zu \"Datenschutz und Sicherheit\"" "Füge deinen ersten Chat hinzu" diff --git a/features/space/impl/src/main/res/values-hr/translations.xml b/features/space/impl/src/main/res/values-hr/translations.xml index 91731dbe71..d1c6ba60a2 100644 --- a/features/space/impl/src/main/res/values-hr/translations.xml +++ b/features/space/impl/src/main/res/values-hr/translations.xml @@ -9,10 +9,20 @@ "Odaberite sobe koje želite napustiti, a za koje niste jedini administrator:" "Morate dodijeliti drugog administratora za ovaj prostor prije nego što ga napustite." + "Vi ste jedini vlasnik %1$s . Prije odlaska morate prenijeti vlasništvo na nekog drugog." "Nećete biti uklonjeni iz sljedećih soba jer ste jedini administrator:" "Želite li napustiti %1$s?" "Vi ste jedini administrator za %1$s" + "Prenesi vlasništvo" + "Soba" + "Dodavanje sobe neće utjecati na pristup sobi. Za promjenu pristupa idite na Postavke sobe > Sigurnost i privatnost." + "sobu" "Prikaži članove" + "Uklanjanje sobe neće utjecati na pristup sobi. Za promjenu pristupa idite na Informacije o sobi > Privatnost i sigurnost." + + "Uklonite %1$d soba od %2$s" + "Uklonite %1$d sobe od %2$s" + "Napusti prostor" "Uloge i dopuštenja" "Sigurnost i privatnost" diff --git a/features/space/impl/src/main/res/values-uz/translations.xml b/features/space/impl/src/main/res/values-uz/translations.xml index ae0bee0a51..3a924aa7ae 100644 --- a/features/space/impl/src/main/res/values-uz/translations.xml +++ b/features/space/impl/src/main/res/values-uz/translations.xml @@ -8,10 +8,20 @@ "Siz yagona administrator bo‘lmagan xonalardan chiqishni xohlasangiz, ularni tanlang:" " Ketishingizdan oldin bu maydon uchun boshqa administrator tayinlashingiz kerak." + "Siz %1$s yagona egasisiz. Ketishdan oldin egalik huquqini boshqa shaxsga o‘tkazishingiz kerak." "Siz quyidagi xona(lar)dan olib tashlanmaysiz, chunki siz yagona administratorsiz:" "%1$s dan chiqasizmi?" "Siz %1$s uchun yagona administratorsiz" + "Egalikni topshirish" + "Xona" + "Xona kiritish xonaga kirishga ta’sir qilmaydi. Ruxsatni o‘zgartirish uchun Xona sozlamalari > Xavfsizlik va maxfiylik rukniga kiring." + "Birinchi xonangizni qo‘shing" "A’zolarni ko‘rish" + "Xona olib tashlansa, unga kirish ruxsatiga ta’sir qilmaydi. Ruxsatni o‘zgartirish uchun Xona haqida > Maxfiylik va xavfsizlik rukniga kiring." + + "%1$d ta xonani %2$sdan olib tashlash" + "%1$d ta xonani %2$sdan olib tashlash" + "Maydondan chiqish" "Rollar va ruxsatlar" "Xavfsizlik va maxfiylik" diff --git a/features/space/impl/src/main/res/values-vi/translations.xml b/features/space/impl/src/main/res/values-vi/translations.xml index a19747d029..f8c0f5b6c5 100644 --- a/features/space/impl/src/main/res/values-vi/translations.xml +++ b/features/space/impl/src/main/res/values-vi/translations.xml @@ -1,5 +1,12 @@ + "Chọn chủ sở hữu" + + "Rời khỏi %1$d phòng và không gian" + + + "Xoá %1$d phòng từ %2$s" + "Rời space" "Vai trò và quyền hạn" diff --git a/features/space/impl/src/main/res/values-zh-rTW/translations.xml b/features/space/impl/src/main/res/values-zh-rTW/translations.xml index f2be9a1875..623f30923e 100644 --- a/features/space/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/space/impl/src/main/res/values-zh-rTW/translations.xml @@ -7,10 +7,19 @@ "這也會將您從此空間中的所有聊天室移除。" "您必須為此空間另外指定一位管理員後才能離開。" + "您是 %1$s 唯一的擁有者。在您離開前,您必須將所有權轉移給其他人。" "您不會被從以下聊天室移除,因為您是唯一的管理員:" "離開 %1$s?" "您是 %1$s 唯一的管理員" + "轉移所有權" + "聊天室" + "新增聊天室不會影響聊天室存取權。要變更存取權,請前往「聊天室設定」→「安全性與隱私權」" + "新增您的第一個聊天室" "檢視成員" + "移除聊天室不會影響聊天室存取權。要變更存取權,請前往「聊天室資訊」→「隱私權與安全性」。" + + "從 %2$s 移除 %1$d 個聊天室" + "離開空間" "角色與權限" "安全與隱私" diff --git a/features/verifysession/impl/src/main/res/values-de/translations.xml b/features/verifysession/impl/src/main/res/values-de/translations.xml index 377da35af3..f50879c573 100644 --- a/features/verifysession/impl/src/main/res/values-de/translations.xml +++ b/features/verifysession/impl/src/main/res/values-de/translations.xml @@ -2,7 +2,7 @@ "Bestätigung unmöglich?" "Erstelle einen neuen Wiederherstellungsschlüssel" - "Verifiziere dieses Gerät, um sichere Chats einzurichten." + "Wähle eine Verifizierungsmethode, um den sicheren Nachrichtenversand einzurichten." "Bestätige deine Identität" "Ein anderes Gerät verwenden" "Wiederherstellungsschlüssel verwenden" @@ -50,5 +50,5 @@ "Nach der Bestätigung kannst du mit der Verifizierung fortfahren." "Akzeptiere die Anfrage für die Verifizierung in deiner anderen Sitzung um fortzufahren." "Warten auf die Annahme der Anfrage" - "Abmelden…" + "Gerät wird entfernt…" diff --git a/features/verifysession/impl/src/main/res/values-et/translations.xml b/features/verifysession/impl/src/main/res/values-et/translations.xml index 2c43794b72..f09202c9c2 100644 --- a/features/verifysession/impl/src/main/res/values-et/translations.xml +++ b/features/verifysession/impl/src/main/res/values-et/translations.xml @@ -3,7 +3,7 @@ "Kas kinnitamine pole võimalik?" "Loo uus taastevõti" "Krüptitud sõnumivahetuse tagamiseks verifitseeri see seade." - "Kinnita, et see oled sina" + "Kinnita oma digitaalne identiteet" "Kasuta teist seadet" "Kasuta taastevõtit" "Nüüd saad saata või lugeda sõnumeid turvaliselt ning kõik sinu vestluspartnerid võivad usaldada seda seadet." diff --git a/features/verifysession/impl/src/main/res/values-hr/translations.xml b/features/verifysession/impl/src/main/res/values-hr/translations.xml index a2ccb7ce0a..91fecd1744 100644 --- a/features/verifysession/impl/src/main/res/values-hr/translations.xml +++ b/features/verifysession/impl/src/main/res/values-hr/translations.xml @@ -2,8 +2,8 @@ "Ne možete potvrditi?" "Izradi novi ključ za oporavak" - "Potvrdite ovaj uređaj kako biste postavili sigurnu razmjenu poruka." - "Potvrdite svoj identitet" + "Odaberite način potvrde za postavljanje sigurne razmjene poruka." + "Potvrdite svoj digitalni identitet" "Upotrijebite drugi uređaj" "Upotrijebi ključ za oporavak" "Sada možete sigurno čitati ili slati poruke, a svatko s kim razgovarate također može vjerovati ovom uređaju." @@ -50,5 +50,5 @@ "Nakon prihvaćanja moći ćete nastaviti s potvrđivanjem." "Prihvatite zahtjev za pokretanje postupka provjere u drugoj sesiji kako biste nastavili." "Čekanje na prihvaćanje zahtjeva" - "Odjavljivanje…" + "Uklanjanje uređaja…" diff --git a/features/verifysession/impl/src/main/res/values-uz/translations.xml b/features/verifysession/impl/src/main/res/values-uz/translations.xml index 26ba7393df..3753b13ec7 100644 --- a/features/verifysession/impl/src/main/res/values-uz/translations.xml +++ b/features/verifysession/impl/src/main/res/values-uz/translations.xml @@ -2,8 +2,8 @@ "Tasdiqlay olmayapsizmi?" "Yangi tiklash kalitini yarating" - "Xavfsiz xabarlashuvni sozlash uchun ushbu qurilmani tasdiqlang." - "Shaxsingizni tasdiqlang" + "Xavfsiz xabar almashinuvni sozlash uchun tasdiqlash usulini tanlang." + "Raqamli shaxsingizni tasdiqlang" "Boshqa qurilmadan foydalanish" "Qayta tiklash kalitidan foydalaning" "Endi xabarlarni xavfsiz tarzda o‘qish yoki yuborish imkoniyatiga egasiz, shuningdek, siz bilan muloqot qilayotgan har qanday kishi ham bu qurilmaga ishonch bildirishi mumkin." @@ -17,7 +17,7 @@ "Quyidagi raqamlarning boshqa sessiyangizda koʻrsatilgan raqamlarga mos kelishini tasdiqlang." "Sonlarni taqqoslash" "Endi xabarlarni boshqa qurilmangizda xavfsiz o‘qish yoki yuborishingiz mumkin." - "Endi xabarlarni yuborish yoki qabul qilishda bu foydalanuvchining shaxsiga ishonishingiz mumkin." + "Endi xabarlarni yuborish yoki qabul qilishda bu foydalanuvchining raqamli identifikatoriga ishonishingiz mumkin." "Qurilma tasdiqlandi" "Tiklash kalitini kiriting" "So‘rov vaqti tugab qoldi, so‘rov rad etildi yoki tekshiruv mos kelmadi." diff --git a/features/verifysession/impl/src/main/res/values-vi/translations.xml b/features/verifysession/impl/src/main/res/values-vi/translations.xml index 7cb5b916cf..4a4b27ab2a 100644 --- a/features/verifysession/impl/src/main/res/values-vi/translations.xml +++ b/features/verifysession/impl/src/main/res/values-vi/translations.xml @@ -1,9 +1,14 @@ + "Không thể xác nhận?" + "Tạo khóa khôi phục mới" "Chọn phương thức xác minh để bật nhắn tin bảo mật." "Xác nhận danh tính kỹ thuật số của bạn" + "Dùng thiết bị khác" + "Sử dụng khóa khôi phục" "Giờ đây bạn có thể đọc và gửi tin nhắn một cách an toàn, và những người bạn trò chuyện cũng có thể tin tưởng thiết bị này." "Thiết bị được xác thực" + "Dùng thiết bị khác" "Đang chờ trên thiết bị khác…" "Có vẻ như có điều gì đó không đúng. Hoặc yêu cầu đã hết thời gian chờ hoặc yêu cầu đã bị từ chối." "Hãy xác nhận rằng các biểu tượng cảm xúc bên dưới khớp với các biểu tượng hiển thị trên thiết bị khác của bạn." diff --git a/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml b/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml index 658e5242f6..5472fba56e 100644 --- a/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml +++ b/features/verifysession/impl/src/main/res/values-zh-rTW/translations.xml @@ -2,8 +2,8 @@ "無法確認?" "建立新的復原金鑰" - "驗證這部裝置以設定安全通訊。" - "確認這是你本人" + "選擇驗證方式以設定安全訊息傳遞。" + "確認您的數位身份" "使用另一部裝置" "使用復原金鑰" "您可以安全地讀取和發送訊息了,與您聊天的人也可以信任這部裝置。" @@ -17,7 +17,7 @@ "確認以下數字是否與其他作業階段中顯示的數字相符。" "比較數字" "現在您可以在其他裝置上安全地閱讀或傳送訊息。" - "現在,您可以在傳送或接收訊息時信任此使用者的身份。" + "現在,您可以在傳送或接收訊息時信任此使用者的數位身份。" "裝置已驗證" "輸入復原金鑰" "請求逾時、請求被拒或是驗證不符。" @@ -42,7 +42,7 @@ "在另外一個已驗證的裝置上開啟應用程式" "為了提昇安全性,請透過比較您裝置上的一組表情符號來驗證此使用者。請透過可信的通訊方式來執行此動作。" "驗證此使用者?" - "為了提昇安全性,另一個使用者希望驗證您的身份。您將會看到一組表情符號以進行比較。" + "為了強化安全性,另一位使用者希望驗證您的數位身分。系統將顯示一組表情符號供您比對。" "您應該會在其他裝置上看到一個彈出式視窗。立刻從那裡開始驗證。" "在其他裝置上開始驗證" "在其他裝置上開始驗證" @@ -50,5 +50,5 @@ "接受後,您就可以繼續進行驗證。" "準備開始驗證,請到您的其他工作階段接受請求。" "等待接受請求" - "正在登出…" + "正在移除裝置……" diff --git a/libraries/matrixui/src/main/res/values-et/translations.xml b/libraries/matrixui/src/main/res/values-et/translations.xml index bd9840940e..abd3830768 100644 --- a/libraries/matrixui/src/main/res/values-et/translations.xml +++ b/libraries/matrixui/src/main/res/values-et/translations.xml @@ -3,5 +3,6 @@ "Saada kutse" "Kas sa soovid alustada vestlust kasutajaga %1$s?" "Kas saadame kutse?" + "Kas alustad vestlust selle uue kontaktiga?" "%1$s (%2$s) saatis sulle kutse" diff --git a/libraries/matrixui/src/main/res/values-fi/translations.xml b/libraries/matrixui/src/main/res/values-fi/translations.xml index daba3555bb..b1b971eadb 100644 --- a/libraries/matrixui/src/main/res/values-fi/translations.xml +++ b/libraries/matrixui/src/main/res/values-fi/translations.xml @@ -3,5 +3,7 @@ "Lähetä kutsu" "Haluaisitko aloittaa keskustelun käyttäjän %1$s kanssa?" "Lähetetäänkö kutsu?" + "Sinulla ei ole tällä hetkellä keskusteluja tämän henkilön kanssa. Vahvista kutsu ennen jatkamista." + "Aloitetaanko keskustelu tämän uuden kontaktin kanssa?" "%1$s (%2$s) kutsui sinut" diff --git a/libraries/matrixui/src/main/res/values-fr/translations.xml b/libraries/matrixui/src/main/res/values-fr/translations.xml index ca952f53c0..7e6466d264 100644 --- a/libraries/matrixui/src/main/res/values-fr/translations.xml +++ b/libraries/matrixui/src/main/res/values-fr/translations.xml @@ -3,5 +3,7 @@ "Envoyer l’invitation" "Voulez-vous entamer une discussion avec %1$s ?" "Envoyer l’invitation ?" + "Vous n’avez actuellement aucune conversation avec cette personne. Confirmez son invitation avant de continuer." + "Entamer une conversation avec ce nouveau contact ?" "%1$s (%2$s) vous a invité(e)" diff --git a/libraries/matrixui/src/main/res/values-hr/translations.xml b/libraries/matrixui/src/main/res/values-hr/translations.xml index 333d8fd7b7..6cd6f9fe7f 100644 --- a/libraries/matrixui/src/main/res/values-hr/translations.xml +++ b/libraries/matrixui/src/main/res/values-hr/translations.xml @@ -3,5 +3,7 @@ "Pošalji pozivnicu" "Želite li započeti razgovor s korisnikom %1$s?" "Želite li poslati pozivnicu?" + "Trenutno nemate razgovora s ovom osobom. Potvrdite pozivanje prije nego što nastavite." + "Želite li započeti razgovor s ovim novim kontaktom?" "Pozvao vas je korisnik %1$s (%2$s)" diff --git a/libraries/matrixui/src/main/res/values-hu/translations.xml b/libraries/matrixui/src/main/res/values-hu/translations.xml index f22454cd16..6bd7999bff 100644 --- a/libraries/matrixui/src/main/res/values-hu/translations.xml +++ b/libraries/matrixui/src/main/res/values-hu/translations.xml @@ -3,5 +3,7 @@ "Meghívó küldése" "Csevegést kezd vele: %1$s?" "Meghívó küldése?" + "Még nem beszélgetett ezzel a személlyel. Folytatás előtt erősítse meg a meghívást." + "Csevegést kezdeményez ezzel az új felhasználóval?" "%1$s (%2$s) meghívta" diff --git a/libraries/matrixui/src/main/res/values-ru/translations.xml b/libraries/matrixui/src/main/res/values-ru/translations.xml index ef6b724c1c..8f01b9ee7f 100644 --- a/libraries/matrixui/src/main/res/values-ru/translations.xml +++ b/libraries/matrixui/src/main/res/values-ru/translations.xml @@ -3,5 +3,7 @@ "Отправить приглашение" "Хотите начать чат с %1$s?" "Отправить приглашение?" + "У Вас нет других чатов с этим пользователем. Подтвердите, что это действительно кого Вы хотите пригласить, прежде чем продолжить." + "Начать чат с этим новым контактом?" "%1$s (%2$s) пригласил(а) вас" diff --git a/libraries/matrixui/src/main/res/values-uz/translations.xml b/libraries/matrixui/src/main/res/values-uz/translations.xml index 63add2d3c0..4510619c7a 100644 --- a/libraries/matrixui/src/main/res/values-uz/translations.xml +++ b/libraries/matrixui/src/main/res/values-uz/translations.xml @@ -3,5 +3,7 @@ "Taklif yuborish" "%1$s bilan chatni boshlashni xohlaysizmi?" "Taklif yuborilsinmi?" + "Ayni paytda bu shaxs bilan hech qanday suhbatingiz yo‘q. Davom etishdan oldin ularni taklif qilishni tasdiqlang." + "Bu yangi kontakt bilan chat boshlansinmi?" "%1$s(%2$s ) sizni taklif qildi" diff --git a/libraries/matrixui/src/main/res/values-zh-rTW/translations.xml b/libraries/matrixui/src/main/res/values-zh-rTW/translations.xml index f851e399fe..1d216abfea 100644 --- a/libraries/matrixui/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/matrixui/src/main/res/values-zh-rTW/translations.xml @@ -3,5 +3,7 @@ "傳送邀請" "您想要開始與 %1$s 聊天嗎?" "傳送邀請?" + "您目前與此人沒有任何聊天紀錄。請確認邀請後再繼續。" + "開始與這位新聯絡人聊天?" "%1$s(%2$s)邀請您" diff --git a/libraries/matrixui/src/main/res/values-zh/translations.xml b/libraries/matrixui/src/main/res/values-zh/translations.xml index aa8479fea0..0a2effc4cf 100644 --- a/libraries/matrixui/src/main/res/values-zh/translations.xml +++ b/libraries/matrixui/src/main/res/values-zh/translations.xml @@ -3,5 +3,6 @@ "发送邀请" "您想与%1$s 开始聊天吗?" "发送邀请?" + "是否与新联系人开始聊天?" "%1$s (%2$s)邀请了你" diff --git a/libraries/push/impl/src/main/res/values-de/translations.xml b/libraries/push/impl/src/main/res/values-de/translations.xml index 6c0e51564a..60e03373f1 100644 --- a/libraries/push/impl/src/main/res/values-de/translations.xml +++ b/libraries/push/impl/src/main/res/values-de/translations.xml @@ -15,6 +15,11 @@ "Der Dienst für UnifiedPush Benachrichtigungen konnte nicht registriert werden. Daher können aktuell keine Push-Benachrichtigungen erhalten werden. Bitte überprüfe die Einstellungen der Benachrichtigungen in der App und den Status des Push-Dienstes." "Du hast neue Nachrichten." + + "Du hast %d neue Nachricht." + "Du hast %d neue Nachrichten." + + "📞 Eingehender Anruf" "Eingehender Anruf" "** Fehler beim Senden - bitte Chat öffnen" "Beitreten" diff --git a/libraries/push/impl/src/main/res/values-hr/translations.xml b/libraries/push/impl/src/main/res/values-hr/translations.xml index 86c458dbf9..eead0db104 100644 --- a/libraries/push/impl/src/main/res/values-hr/translations.xml +++ b/libraries/push/impl/src/main/res/values-hr/translations.xml @@ -17,6 +17,11 @@ "Distributer obavijesti UnifiedPush nije mogao biti registriran, tako da više nećete primati obavijesti. Provjerite postavke obavijesti u aplikaciji i status distributera push obavijesti." "Imate nove poruke." + + "Imate%d novu poruku." + "Imate %d novi poruka." + + "📞 Dolazni poziv" "📹 Dolazni poziv" "** Slanje nije uspjelo – otvorite sobu" "Pridruži se" diff --git a/libraries/push/impl/src/main/res/values-uz/translations.xml b/libraries/push/impl/src/main/res/values-uz/translations.xml index 1058fdd1d2..d4a018ab80 100644 --- a/libraries/push/impl/src/main/res/values-uz/translations.xml +++ b/libraries/push/impl/src/main/res/values-uz/translations.xml @@ -15,6 +15,11 @@ "UnifiedPush bildirishnoma tarqatuvchisini roʻyxatdan oʻtkazib boʻlmadi, shuning uchun siz endi bildirishnomalarni olmaysiz. Iltimos, ilovaning bildirishnoma sozlamalarini va push distribyutor holatini tekshiring." "Sizda yangi xabarlar bor." + + "Sizda %d ta yangi xabar bor." + "Sizda %d ta yangi xabar bor." + + "📞 Kiruvchi qo‘ng‘iroq" "📹 Kiruvchi qoʻngʻiroq" "** Yuborilmadi - iltimos, xonani oching" "Qo\'shilish" diff --git a/libraries/push/impl/src/main/res/values-vi/translations.xml b/libraries/push/impl/src/main/res/values-vi/translations.xml index 5592ff0e3a..b286c8fc29 100644 --- a/libraries/push/impl/src/main/res/values-vi/translations.xml +++ b/libraries/push/impl/src/main/res/values-vi/translations.xml @@ -11,7 +11,12 @@ "%d thông báo" + "Không thể đăng ký trình phân phối thông báo UnifiedPush, vì vậy bạn sẽ không nhận được thông báo nữa. Vui lòng kiểm tra cài đặt thông báo của ứng dụng và trạng thái của trình phân phối thông báo." "Bạn có tin nhắn mới." + + "Bạn có %d tin nhắn mới." + + "📞 Cuộc gọi đến" "📹 Cuộc gọi đến" "** Không gửi được - vui lòng mở phòng" "Tham gia" @@ -20,6 +25,7 @@ "%d lời mời" "Đã mời bạn trò chuyện" + "%1$s đã mời bạn trò chuyện" "Đã nhắc đến bạn: %1$s" "Tin nhắn mới" @@ -29,8 +35,13 @@ "Đánh dấu đã đọc" "Trả lời nhanh" "Đã mời bạn tham gia phòng" + "%1$s đã mời bạn tham gia phòng chat" "Tôi" + "%1$s đã đề cập hoặc trả lời" + "Mời bạn tham gia không gian này." + "%1$s đã mời bạn tham gia không gian này." "Bạn đang xem thông báo! Bấm vào đây!" + "Chuỗi cuộc trò chuyện trong: %1$s" "%1$s:%2$s" "%1$s: %2$s %3$s" @@ -45,6 +56,9 @@ "Đồng bộ hóa trong nền" "Dịch vụ của Google" "Không tìm thấy Dịch vụ Google Play hợp lệ. Thông báo có thể không hoạt động đúng cách." + + "Bạn đã chặn người dùng %1$d. Bạn sẽ không nhận được thông báo từ người này." + "Người dùng bị chặn" "Hãy đảm bảo rằng ứng dụng hỗ trợ ít nhất một nhà cung cấp thông báo đẩy." "Không tìm thấy hỗ trợ từ nhà cung cấp thông báo đẩy." diff --git a/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml b/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml index 2d289e9a9e..207f962b90 100644 --- a/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml +++ b/libraries/push/impl/src/main/res/values-zh-rTW/translations.xml @@ -13,6 +13,10 @@ "Unified Push 通知散佈程式註冊失敗,因此您無法再收到通知。請檢查應用程式的通知設定與推播散佈程式的狀態。" "您有新訊息。" + + "您有 %d 則新訊息。" + + "📞 來電" "📹 來電" "** 無法傳送,請開啟聊天室" "加入" @@ -34,6 +38,8 @@ "%1$s 邀請您加入聊天室" "我" "%1$s 提及或回覆" + "已邀請您加入空間" + "%1$s 已邀請您的加入此空間" "您正在查看通知!點我!" "在 %1$s 的討論串" "%1$s:%2$s" diff --git a/libraries/pushproviders/unifiedpush/src/main/res/values-vi/translations.xml b/libraries/pushproviders/unifiedpush/src/main/res/values-vi/translations.xml new file mode 100644 index 0000000000..3305adad2a --- /dev/null +++ b/libraries/pushproviders/unifiedpush/src/main/res/values-vi/translations.xml @@ -0,0 +1,6 @@ + + + + "%1$d nhà phân phối đã tìm thấy: %2$s ." + + diff --git a/libraries/textcomposer/impl/src/main/res/values-vi/translations.xml b/libraries/textcomposer/impl/src/main/res/values-vi/translations.xml index 42b78d23f3..5395221a6d 100644 --- a/libraries/textcomposer/impl/src/main/res/values-vi/translations.xml +++ b/libraries/textcomposer/impl/src/main/res/values-vi/translations.xml @@ -4,11 +4,18 @@ "Chuyển đổi danh sách dấu đầu dòng" "Hủy và đóng định dạng văn bản" "Bật/tắt khối mã" + "Thêm chú thích" + "Tin nhắn được mã hóa…" "Tin nhắn…" + "Tin nhắn chưa được mã hóa…" "Tạo liên kết" "Sửa liên kết" + "%1$s, tình trạng: %2$s" "Áp dụng định dạng in đậm" "Áp dụng định dạng in nghiêng" + "Đã tắt" + "tắt" + "bật" "Áp dụng định dạng gạch ngang" "Áp dụng định dạng gạch chân" "Bật/tắt chế độ toàn màn hình" 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 38d9ac3d8e..57bb2427fc 100644 --- a/libraries/ui-strings/src/main/res/values-cs/translations.xml +++ b/libraries/ui-strings/src/main/res/values-cs/translations.xml @@ -474,7 +474,6 @@ Opravdu chcete pokračovat?" "Odstranit %1$s" "Nastavení" "Výběr média se nezdařil, zkuste to prosím znovu." - "Vítejte zpět" "Přidržte zprávu a vyberte „%1$s“, kterou chcete zahrnout sem." "Připněte důležité zprávy, aby je bylo možné snadno najít" 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 e12e049469..e9ed8edaa4 100644 --- a/libraries/ui-strings/src/main/res/values-da/translations.xml +++ b/libraries/ui-strings/src/main/res/values-da/translations.xml @@ -466,7 +466,6 @@ Er du sikker på, at du vil fortsætte?" "Fjern %1$s" "Indstillinger" "Det lykkedes ikke at vælge medie. Prøv igen." - "Velkommen tilbage" "Tryk på en besked og vælg \"%1$s\" for at inkludere den her." "Fastgør vigtige beskeder, så de let kan opdages" 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 1d0f26085e..81cb12eb78 100644 --- a/libraries/ui-strings/src/main/res/values-de/translations.xml +++ b/libraries/ui-strings/src/main/res/values-de/translations.xml @@ -1,6 +1,7 @@ "Reaktion hinzufügen: %1$s" + "Adresse" "Avatar" "Nachrichtentextfeld minimieren" "Löschen" @@ -26,9 +27,12 @@ "Pausieren" "Sprachnachricht, Dauer:%1$s, aktuelle Position: %2$s" "PIN-Feld" + "Fixierter Standort" "Abspielen" + "Wiedergabegeschwindigkeit" "Umfrage" "Umfrage beendet" + "QR-Code" "Reagiere mit %1$s" "Mit anderen Emojis reagieren" "Gelesen von %1$s und %2$s" @@ -42,9 +46,11 @@ "Entferne Reaktionen mit %1$s" "Avatar" "Dateien senden" + "Standort des Absenders" "Zeitlich begrenzte Handlung erforderlich, du hast eine Minute Zeit zur Verifizierung" "Passwort anzeigen" "Anruf starten" + "Sprachanruf starten" "Stillgelegter Chat" "Nutzer-Avatar" "Nutzer-Menü" @@ -114,6 +120,7 @@ "Space verlassen" "Mehr laden…" "Konto verwalten" + "Konto & Geräte verwalten" "Geräte verwalten" "Chats und Gruppen konfigurieren" "Nachricht" @@ -153,16 +160,18 @@ "Sprachnachricht senden" "Teilen" "Link teilen" + "Live-Standort teilen" "Zeige" "Erneut anmelden" - "Abmelden" - "Trotzdem abmelden" + "Dieses Gerät entfernen" + "Dieses Gerät trotzdem entfernen" "Überspringen" "Start" "Chat starten" "Neu beginnen" "Verifizierung starten" "Tippe, um die Karte zu laden" + "Beenden" "Foto aufnehmen" "Für Optionen tippen" "Übersetzen" @@ -183,6 +192,7 @@ "Erweiterte Einstellungen" "ein Bild" "Analysedaten" + "Benachrichtigungen werden synchronisiert…" "Du hast den Chat verlassen" "Du wurdest aus der Sitzung abgemeldet." "Erscheinungsbild" @@ -216,6 +226,7 @@ "Leere Datei" "Verschlüsselung" "Verschlüsselung aktiviert" + "Endet um %1$s" "PIN eingeben" "Fehler" "Es ist ein Fehler aufgetreten. Du erhältst eventuell keine Benachrichtigungen für neue Nachrichten. Bitte behebe den Fehler in den Einstellungen. @@ -242,6 +253,8 @@ Grund: %1$s." "Zeile in die Zwischenablage kopiert" "Link in die Zwischenablage kopiert" "Neues Gerät verknüpfen" + "Live-Standort" + "Live-Standort teilen beendet" "Laden…" "Mehr wird geladen…" @@ -268,6 +281,7 @@ Grund: %1$s." "Offline" "Open-Source-Lizenzen" "oder" + "Weitere Optionen" "Passwort" "Personen" "Permalink" @@ -285,8 +299,10 @@ Grund: %1$s." "Vorbereitung läuft …" "Datenschutz­erklärung" + "Privat" "Privater Chat" "Privater Space" + "Öffentlich" "Öffentlicher Chat" "Öffentlicher Space" "Reaktion" @@ -335,12 +351,14 @@ Grund: %1$s." "Einstellungen" "Space teilen" "Neue Mitglieder sehen den Nachrichtenverlauf" + "Geteilter Live-Standort" "Geteilter Standort" "Gemeinsamer Space" - "Abmelden" + "Gerät entfernen" "Es ist ein Fehler aufgetreten." "Wir haben ein Problem festgestellt. Bitte versuch es erneut." "Space" + "Space Mitglieder" "Worum geht es hier?" "%1$d Space" @@ -356,12 +374,13 @@ Grund: %1$s." "Text" "Hinweise von Drittanbietern" "Thread" + "Threads" "Thema" "Worum geht is in diesem Chat?" "Entschlüsselung nicht möglich" "Von einem ungesicherten Gerät gesendet" "Du hast keinen Zugriff auf diese Nachricht." - "Die verifizierte Identität des Senders hat sich geändert" + "Die verifizierte Identität des Senders wurde zurückgesetzt" "Einladungen konnten nicht an einen oder mehrere Nutzer gesendet werden." "Einladung(en) konnte(n) nicht gesendet werden" "Entsperren" @@ -386,17 +405,19 @@ Grund: %1$s." "Sprachnachricht" "Warten…" "Warte auf diese Nachricht" + "Warten auf Live-Standort…" "Jeder kann den Nachrichtenverlauf sehen" "Du" "%1$s (%2$s) hat diese Nachricht geteilt, weil du nicht im Chat warst, als sie verschickt wurde." "Diese Nachricht wurde von %1$s weitergeleitet, da du zum Zeitpunkt des Versands kein Mitglied der Gruppe warst." "Diese Gruppe wurde so konfiguriert, dass neue Mitglieder den vergangenen Nachrichtenverlauf lesen können. %1$s" - "%1$s\'s Identität has sich geändert. %2$s" - "%1$s\'s %2$s Identität hat sich geändert. %3$s" + "Die Identität von %1$s wurde zurückgesetzt. %2$s" + "Die Identität von %1$s %2$s wurde zurückgesetzt. %3$s" "(%1$s)" - "Die Identität von %1$s hat sich geändert." - "Die Identität von %1$s\'s %2$s hat sich geändert. %3$s" + "Die Identität von %1$s wurde zurückgesetzt." + "Die Identität von %1$s %2$s wurde zurückgesetzt. %3$s" "Verifizierung zurückziehen" + "Zugriff erlauben" "Der Link %1$s führt dich zu einer anderen Seite %2$s. Möchtest du wirklich fortfahren?" @@ -453,7 +474,7 @@ Möchtest du wirklich fortfahren?" "Fixierte Nachrichten" "Du wirst jetzt zu deinem %1$s Konto geleitet, um deine Identität zurückzusetzen. Danach wirst du zur App zurückgebracht." - "Kannst du das nicht bestätigen? Gehe zu deinem Konto, um deine Identität zurückzusetzen." + "Bestätigung nicht möglich? Rufe dein Konto auf, um deine digitale Identität zurückzusetzen." "Verifizierung zurückziehen und senden" "Du kannst deine Verifizierung zurückziehen und diese Nachricht trotzdem senden, oder du kannst vorerst abbrechen und es später noch einmal versuchen, nachdem du %1$s erneut verifiziert hast." "Deine Nachricht wurde nicht gesendet, da die verifizierte Identität von %1$s zurückgesetzt wurde" @@ -480,11 +501,14 @@ Möchtest du wirklich fortfahren?" "In Google Maps öffnen" "In OpenStreetMap öffnen" "Diesen Standort teilen" + "Optionen zum Teilen" "Von dir erstellte oder beigetretene Spaces." "%1$s • %2$s" "Erstelle einen Space, um Chats zu organisieren" "%1$s Space" "Spaces" + "Geteilt %1$s" + "Auf der Karte" "Nachricht nicht gesendet, weil sich die verifizierte Identität von %1$s geändert hat." "Die Nachricht wurde nicht gesendet, weil %1$s nicht alle Geräte verifiziert hat." "Die Nachricht wurde nicht gesendet, weil du eines oder mehrere deiner Geräte nicht verifiziert hast." 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 ee4d782595..beb97c54d1 100644 --- a/libraries/ui-strings/src/main/res/values-el/translations.xml +++ b/libraries/ui-strings/src/main/res/values-el/translations.xml @@ -459,7 +459,6 @@ "Αφαίρεση %1$s" "Ρυθμίσεις" "Αποτυχία επιλογής πολυμέσου, δοκίμασε ξανά." - "Καλώς ήρθατε ξανά" "Πάτα σε ένα μήνυμα και επέλεξε «%1$s» για να συμπεριληφθεί εδώ." "Καρφίτσωσε σημαντικά μηνύματα, ώστε να μπορούν να εντοπιστούν εύκολα" 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 53f2178a1a..beedf175bd 100644 --- a/libraries/ui-strings/src/main/res/values-et/translations.xml +++ b/libraries/ui-strings/src/main/res/values-et/translations.xml @@ -27,6 +27,7 @@ "Peata" "Häälsõnum, kestus:%1$s, praegune asukoht: %2$s" "PIN-koodi väli" + "Esiletõstetud asukoht" "Esita" "Taasesituse kiirus" "Küsitlus" @@ -45,9 +46,12 @@ "Eemalda reageerimine: %1$s" "Jututoa tunnuspilt" "Saada faile" + "Saatja asukoht" "Palun tee see ajapiiranguga toiming, sul on aega üks minut" "Näita salasõna" "Helista" + "Alusta videokõnet" + "Helista" "Lõpetatuks märgitud jututuba" "Kasutaja tunnuspilt" "Kasutajamenüü" @@ -117,6 +121,7 @@ "Lahku kogukonnast" "Näita veel" "Halda kasutajakontot" + "Halda kasutajakontosid ja seadmeid" "Halda seadmeid" "Halda jututuba" "Saada sõnum" @@ -156,16 +161,18 @@ "Saada häälsõnum" "Jaga" "Jaga linki" + "Jaga asukohta reaalajas" "Näita" "Logi uuesti sisse" - "Logi välja" - "Ikkagi logi välja" + "Eemalda see seade" + "Eemalda see seade ikkagi" "Jäta vahele" "Alusta" "Alusta vestlust" "Alusta uuesti" "Alusta verifitseerimist" "Kaardi laadimiseks klõpsa" + "Lõpeta" "Pildista" "Valikuteks klõpsa" "Tõlgi" @@ -186,6 +193,7 @@ "Täiendavad seadistused" "pilt" "Analüütika" + "Sünkroonin teavitusi…" "Sina lahkusid jututoast" "Sa olid sessioonist väljaloginud" "Välimus" @@ -362,6 +370,7 @@ Põhjus: %1$s." "Tekst" "Kolmandate osapoolte teatised" "Jutulõng" + "Jutulõngad" "Teema" "Mis on selle jututoa mõte?" "Dekrüptimine ei olnud võimalik" @@ -450,6 +459,8 @@ Kas sa oled kindel, et soovid jätkata?" "Valikud" "Kustuta: %1$s" "Seadistused" + "Mitte keegi ei jaga oma asukohta" + "Asukoht on jagamisel reaalajas" "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" @@ -486,6 +497,7 @@ Kas sa oled kindel, et soovid jätkata?" "Ava Google Mapsis" "Ava OpenStreetMapis" "Jaga seda asukohta" + "Jagamise valikud" "Sinu loodud kogukonnad ning need, millega oled liitunud." "%1$s • %2$s" "Jututubade haldamiseks võid luua kogukondi" 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 7be84a8716..48601352ba 100644 --- a/libraries/ui-strings/src/main/res/values-fi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fi/translations.xml @@ -50,6 +50,7 @@ "Aikarajoitettu toimenpide vaaditaan, sinulla on yksi minuutti aikaa vahvistaa" "Näytä salasana" "Aloita puhelu" + "Aloita videopuhelu" "Aloita äänipuhelu" "Haudattu huone" "Käyttäjän avatar" @@ -466,14 +467,14 @@ Haluatko varmasti jatkaa?" "Vaihtoehdot" "Poista %1$s" "Asetukset" + "Kukaan ei jaa sijaintiaan" + "Jaetaan reaaliaikaista sijaintia" + + "%1$d henkilö" + "%1$d henkilöä" + + "Kartalla" "Median valinta epäonnistui, yritä uudelleen." - "Avaa Element Classic" - "Avaa Element Classic laitteellasi" - "Mene kohtaan \"Asetukset\" > \"Tietoturva ja yksityisyys\"" - "Osiossa \"Salausavainten hallinta\", paina \"Salattujen viestien palautus\"." - "Noudata ohjeita" - "Palaa takaisin %1$s -sovellukseen" - "Tervetuloa takaisin" "Paina viestiä ja valitse “%1$s” lisätäksesi sen tänne." "Kiinnitä tärkeät viestit, jotta ne löytyvät helposti." @@ -497,6 +498,7 @@ Haluatko varmasti jatkaa?" "Viesti huoneessa %1$s" "Laajenna" "Pienennä" + "Jaetaan reaaliaikaista sijaintia" "Katselet jo tätä huonetta!" "%1$s / %2$s" "Kiinnitetty viesti %1$s" 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 bec6d7f4ca..bc109f5ff7 100644 --- a/libraries/ui-strings/src/main/res/values-fr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-fr/translations.xml @@ -50,6 +50,7 @@ "Action limitée dans le temps requise, vous avez une minute pour effectuer la vérification" "Afficher le mot de passe" "Démarrer un appel" + "Passer un appel vidéo" "Lancer un appel vocal" "Salon clôturé" "Avatar de l’utilisateur" @@ -466,15 +467,14 @@ Raison : %1$s." "Options" "Supprimer %1$s" "Paramètres" + "Personne ne partage sa position" + "Partage de la position en direct" + + "%1$d personne" + "%1$d personnes" + + "Sur la carte" "Échec de la sélection du média, veuillez réessayer." - "Ouvrir Element Classic" - "Ouvrez Element Classic sur votre appareil" - "Aller à Paramètres > Sécurité et vie privée" - "Dans Gestion des clés cryptographiques, sélectionnez Récupération des messages chiffrés" - "Suivez les instructions pour activer votre stockage de clés" - "Revenez à %1$s" - "Activez le stockage de vos clés avant de continuer avec %1$s" - "Bon retour parmi nous" "Cliquez (clic long) sur un message et choisissez « %1$s » pour qu‘il apparaisse ici." "Épinglez les messages importants pour leur donner plus de visibilité" @@ -498,6 +498,7 @@ Raison : %1$s." "Message dans %1$s" "Développer" "Réduire" + "Partage de la position en direct" "Vous êtes déjà dans ce salon!" "%1$s sur %2$s" "%1$s Messages épinglés" 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 1bb8ceb426..61c9ea54e2 100644 --- a/libraries/ui-strings/src/main/res/values-hr/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hr/translations.xml @@ -1,6 +1,7 @@ "Dodaj reakciju: %1$s" + "Adresa" "Avatar" "Minimiziraj tekstno polje poruke" "Izbriši" @@ -27,9 +28,12 @@ "Pauziraj" "Glasovna poruka, trajanje: %1$s, trenutačno zaustavljeno na: %2$s" "Polje za PIN" + "Prikvačena lokacija" "Reproduciraj" + "Brzina reprodukcije" "Anketa" "Završena anketa" + "QR kod" "Reagiraj s %1$s" "Reagiraj s drugim emotikonima" "Pročitali %1$s i %2$s" @@ -44,9 +48,12 @@ "Ukloni reakciju s %1$s" "Avatar sobe" "Pošalji datoteke" + "Lokacija pošiljatelja" "Potrebna je vremenski ograničena radnja, imate jednu minutu za potvrdu" "Prikaži zaporku" "Započni poziv" + "Započni videopoziv" + "Započni glasovni poziv" "Soba označena za uklanjanje" "Korisnički avatar" "Korisnički izbornik" @@ -58,6 +65,7 @@ "Vaš avatar" "Prihvati" "Dodaj opis" + "Dodaj postojeće sobe" "Dodaj na vremensku traku" "Natrag" "Poziv" @@ -76,7 +84,8 @@ "Kopiraj poveznicu u poruku" "Kopiraj tekst" "Stvori" - "Stvori sobu" + "Napravi sobu" + "Stvori prostor" "Deaktiviraj" "Deaktiviraj račun" "Odbij" @@ -93,6 +102,7 @@ "Omogući" "Završi anketu" "Unesite PIN" + "Istražite javne prostore" "Završi" "Zaboravili ste zaporku?" "Proslijedi" @@ -113,6 +123,7 @@ "Napusti prostor" "Učitaj više" "Upravljanje računom" + "Upravljanje računom i uređajima" "Upravljanje uređajima" "Upravljaj sobama" "Poruka" @@ -152,16 +163,18 @@ "Pošalji glasovnu poruku" "Podijeli" "Podijeli poveznicu" + "Dijeljenje lokacije uživo" "Prikaži" "Ponovno se prijavite" - "Odjava" - "Svejedno se odjavi" + "Ukloni ovaj uređaj" + "Ukloni ovaj uređaj svejedno" "Preskoči" "Započni" "Započni razgovor" "Kreni ispočetka" "Započni provjeru" "Dodirnite za učitavanje karte" + "Zaustavi" "Uslikaj" "Dodirnite za mogućnosti" "Prevedi" @@ -182,6 +195,7 @@ "Napredne postavke" "slika" "Analitika" + "Sinkronizacija obavijesti…" "Napustili ste sobu" "Odjavljeni ste iz sesije" "Izgled" @@ -194,6 +208,7 @@ "Kopirano u međuspremnik" "Autorsko pravo" "Stvaranje sobe…" + "Stvaranje prostora…" "Zahtjev je otkazan" "Napustio/la je sobu" "Napušteni prostor" @@ -214,6 +229,7 @@ "Prazna datoteka" "Šifriranje" "Šifriranje je omogućeno" + "Završava u %1$s" "Unesite svoj PIN" "Pogreška" "Došlo je do pogreške; možda nećete primati obavijesti za nove poruke. Riješite problem s obavijestima u postavkama. @@ -240,6 +256,8 @@ Razlog: %1$s ." "Redak je kopiran u međuspremnik" "Poveznica je kopirana u međuspremnik." "Poveži novi uređaj" + "Lokacija uživo" + "Prikaz lokacije uživo je završio" "Učitavanje…" "Učitava se još…" @@ -268,6 +286,7 @@ Razlog: %1$s ." "Izvan mreže" "Licencije otvorenog koda" "ili" + "Ostale opcije" "Zaporka" "Osobe" "Stalna poveznica" @@ -286,8 +305,10 @@ Razlog: %1$s ." "Priprema…" "Pravilnik o zaštiti privatnosti" + "Privatno" "Privatna soba" "Privatni prostor" + "Javno" "Javna soba" "Javni prostor" "Reakcija" @@ -295,6 +316,7 @@ Razlog: %1$s ." "Razlog" "Ključ za oporavak" "Osvježavanje…" + "U tijeku je uklanjanje…" "%1$d odgovor" "%1$d odgovora" @@ -305,6 +327,7 @@ Razlog: %1$s ." "Prijavi problem" "Prijava je podnesena" "Uređivač obogaćenog teksta" + "Uloga" "Soba" "Naziv sobe" "npr. naziv vašeg projekta" @@ -321,6 +344,10 @@ Razlog: %1$s ." "Sigurnost" "Vidio/la" "Odaberi račun" + + "%1$d odabrano" + "%1$d odabrano" + "Pošalji" "Slanje…" "Slanje nije uspjelo" @@ -331,12 +358,15 @@ Razlog: %1$s ." "URL poslužitelja" "Postavke" "Podijeli prostor" + "Novi članovi vide povijest" + "Dijeljena lokacija uživo" "Podijeljena lokacija" "Zajednički prostor" - "Odjava je u tijeku" + "Uklanjanje uređaja" "Nešto je pošlo po zlu" "Naišli smo na problem. Pokušajte ponovno." "Prostor" + "Članovi prostora" "O čemu se radi u ovom prostoru?" "%1$d prostor" @@ -346,12 +376,14 @@ Razlog: %1$s ." "Započinjanje razgovora…" "Naljepnica" "Uspjeh" + "Preporučeno" "Prijedlozi" "Sinkronizacija" "Sustav" "Tekst" "Obavijesti trećih strana" "Nit" + "Niti" "Tema" "O čemu je ova soba?" "Nije moguće dešifrirati" @@ -382,7 +414,11 @@ Razlog: %1$s ." "Glasovna poruka" "Čekanje…" "Čekam ovu poruku" + "Čekanje lokacije uživo…" + "Svatko može vidjeti povijest" "Vi" + "%1$s(%2$s ) je podijelio/la ovu poruku jer niste bili u sobi kada je poslana." + "%1$spodijelio/la je ovu poruku jer nisi bio/la u sobi kada je poslana." "Ova je soba konfigurirana tako da novi članovi mogu čitati stare poruke. %1$s" "Identitet korisnika %1$s je poništen. %2$s" "Identitet korisnika %1$s %2$s je poništen. %3$s" @@ -390,6 +426,7 @@ Razlog: %1$s ." "Identitet korisnika %1$s je poništen." "Identitet korisnika %1$s %2$s je poništen. %3$s" "Povuci provjeru" + "Dopusti pristup" "Poveznica %1$s vodi vas na drugo mrežno mjesto %2$s Jeste li sigurni da želite nastaviti?" @@ -419,6 +456,7 @@ Jeste li sigurni da želite nastaviti?" "%1$s nije mogao pristupiti vašoj lokaciji. Pokušajte ponovno poslije." "Prijenos vaše glasovne poruke nije uspio." "Soba više ne postoji ili pozivnica više ne vrijedi." + "Omogućite GPS za pristup značajkama temeljenim na lokaciji." "Poruka nije pronađena" "%1$s nema dopuštenje za pristup vašoj lokaciji. Pristup možete omogućiti u postavkama." "%1$s nema dopuštenje za pristup vašoj lokaciji. Omogućite pristup u nastavku." @@ -462,6 +500,7 @@ Jeste li sigurni da želite nastaviti?" "Poruka u sobi %1$s" "Proširi" "Smanji" + "Dijeljenje lokacije uživo" "Već gledam ovu sobu!" "%1$s od %2$s" "%1$s Prikvačene poruke" @@ -474,10 +513,14 @@ Jeste li sigurni da želite nastaviti?" "Otvori u Google Maps" "Otvori u OpenStreetMap" "Podijeli ovu lokaciju" + "Opcije dijeljenja" "Prostori koje ste stvorili ili kojima ste se pridružili." "%1$s • %2$s" + "Stvorite prostore za organizaciju soba" "Prostor %1$s" "Prostori" + "Dijeljeno %1$s" + "Na karti" "Poruka nije poslana jer je poništen potvrđeni identitet korisnika %1$s." "Poruka nije poslana jer %1$s nije potvrdio sve uređaje." "Poruka nije poslana jer niste potvrdili jedan svoj uređaj ili više njih." 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 9586b392e9..06f49eba93 100644 --- a/libraries/ui-strings/src/main/res/values-hu/translations.xml +++ b/libraries/ui-strings/src/main/res/values-hu/translations.xml @@ -50,6 +50,7 @@ "Időkorlátos művelet szükséges, egy perce van az ellenőrzésre" "Jelszó megjelenítése" "Hanghívás indítása" + "Videohívás indítása" "Hanghívás indítása" "Elévült szoba" "Felhasználói profilkép" @@ -465,15 +466,14 @@ Biztos, hogy folytatja?" "Lehetőségek" "Eltávolítás: %1$s" "Beállítások" + "Senki sem osztja meg a tartózkodási helyét" + "Élő helymegosztás" + + "%1$d személy" + "%1$d személy" + + "A térképen" "Nem sikerült kiválasztani a médiát, próbálja újra." - "Nyissa meg az Element Classic alkalmazást" - "Nyissa meg az Element Classic alkalmazást az eszközén" - "Lépjen a Beállítások > Biztonság és adatvédelem menüponthoz" - "A Kriptográfiai kulcsok kezelése részben válassza a Titkosított üzenetek helyreállítása lehetőséget" - "Kövesse az utasításokat a kulcstároló engedélyezéséhez" - "Térjen vissza ide: %1$s" - "Engedélyezze a kulcstárolást a folytatás előtt ide: %1$s" - "Üdvözöljük újra!" "Nyomjon hosszan az üzenetre, és válassza a „%1$s” lehetőséget, hogy itt szerepeljen." "Tűzze ki a fontos üzeneteket, hogy könnyen felfedezhetők legyenek" @@ -497,6 +497,7 @@ Biztos, hogy folytatja?" "Üzenet a következőben: %1$s" "Kibontás" "Csökkentés" + "Élő helymegosztás" "Már ezt a szobát nézi!" "%1$s. / %2$s" "%1$s kitűzött üzenet" 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 0d73a8c121..824b9f6441 100644 --- a/libraries/ui-strings/src/main/res/values-it/translations.xml +++ b/libraries/ui-strings/src/main/res/values-it/translations.xml @@ -468,14 +468,6 @@ Sei sicuro di voler continuare?" "Rimuovi %1$s" "Impostazioni" "Selezione del file multimediale fallita, riprova." - "Apri Element Classic" - "Apri Element Classic sul tuo dispositivo" - "Vai su Impostazioni > Sicurezza & privacy" - "Nella gestione delle chiavi crittografiche, seleziona Recupero dei messaggi cifrati" - "Segui le istruzioni per abilitare l\'archiviazione delle chiavi" - "Torna a %1$s" - "Abilita l\'archivio delle chiavi prima di procedere con %1$s" - "Bentornato" "Premi su un messaggio e scegli “%1$s” per includerlo qui." "Fissa i messaggi importanti così che possano essere trovati facilmente" 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 f77a92966b..8d0345e0e0 100644 --- a/libraries/ui-strings/src/main/res/values-ja/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ja/translations.xml @@ -280,7 +280,7 @@ "または" "他のオプション" "パスワード" - "人" + "人々" "固定リンク" "権限" "ピン留め" @@ -458,16 +458,13 @@ "選択肢" "%1$s を削除" "設定" + "誰も位置情報を共有していません" + "ライブ位置情報を共有しています" + + "%1$d 人" + + "地図上" "ファイルの選択に失敗しました。再試行してください。" - "Element Classic を開く" - "Element Classic をこの端末で開く" - "「設定- セキュリティとプライバシー」に移動します" - "暗号鍵の管理から、暗号化されたメッセージの回復を選択します" - "指示に従って、鍵の保管庫を有効化してください" - "%1$s に戻ってください" - "%1$s に続行する前に、鍵の保管庫を有効化してください" - "アカウントを確認中" - "おかえりなさい" "メッセージを長押しし \"%1$s\" を選択してください" "重要なメッセージをピン留めして容易に見つけられるようにします" 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 4174e4d15d..6a87870658 100644 --- a/libraries/ui-strings/src/main/res/values-ko/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ko/translations.xml @@ -460,14 +460,6 @@ "%1$s 제거" "설정" "미디어 선택에 실패했습니다. 다시 시도해 주세요." - "Element Classic 열기" - "기기에서 Element Classic 앱을 열어 주세요" - "설정 > 보안 및 개인정보 보호로 이동하세요" - "암호화 키 관리에서 \'암호화된 메시지 복구\'를 선택하세요" - "안내에 따라 키 저장소를 활성화해 주세요" - "%1$s(으)로 돌아가기" - "%1$s(으)로 진행하기 전에 키 저장소를 활성화해 주세요." - "다시 오신 것을 환영합니다" "메시지를 누르고 \"%1$s\" 를 선택하여 여기에 포함합니다." "중요한 메시지를 고정하여 쉽게 찾을 수 있도록 합니다" 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 1ebbceedd5..280209f6a5 100644 --- a/libraries/ui-strings/src/main/res/values-lt/translations.xml +++ b/libraries/ui-strings/src/main/res/values-lt/translations.xml @@ -170,7 +170,6 @@ "%1$s Android" "Papurtykite, kad praneštumėte apie klaidą" "Nepavyko pasirinkti laikmenos, pabandykite dar kartą." - "Sveiki sugrįžę" "Nepavyko apdoroti įkeliamos laikmenos, bandykite dar kartą." "Nepavyko gauti naudotojo išsamios informacijos." "Bendrinti vietą" 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 f563a89258..fc641df34d 100644 --- a/libraries/ui-strings/src/main/res/values-nb/translations.xml +++ b/libraries/ui-strings/src/main/res/values-nb/translations.xml @@ -455,7 +455,6 @@ Er du sikker på at du vil fortsette?" "Fjern %1$s" "Innstillinger" "Kunne ikke velge medium, prøv igjen." - "Velkommen tilbake" "Trykk på en melding og velg “%1$s” for å inkludere her." "Fest viktige meldinger slik at de lett kan ses" 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 5e4d7f9b67..bb423b5b10 100644 --- a/libraries/ui-strings/src/main/res/values-ru/translations.xml +++ b/libraries/ui-strings/src/main/res/values-ru/translations.xml @@ -476,15 +476,15 @@ "Параметры" "Удалить %1$s" "Настройки" + "Никто не делится своим местоположением" + "Местоположение отправляется в реальном времени" + + "%1$d человек" + "%1$d человек" + "%1$d людей" + + "На карте" "Не удалось выбрать медиа, попробуйте еще раз." - "Открыть Element Classic" - "Откройте Element Classic на своем устройстве." - "Перейдите в Настройки > Безопасность и конфиденциальность" - "В разделе «Управление криптографическими ключами» выбери «Восстановление зашифрованных сообщений»" - "Следуйте инструкциям, чтобы активировать хранилище ключей" - "Вернитесь к %1$s" - "Перед продолжением активируйте хранилище ключей %1$s" - "С возвращением" "Нажмите на сообщение и выберите «%1$s», чтобы добавить его сюда." "Закрепите важные сообщения, чтобы их можно было легко найти" 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 aada6634d2..2542de084e 100644 --- a/libraries/ui-strings/src/main/res/values-uz/translations.xml +++ b/libraries/ui-strings/src/main/res/values-uz/translations.xml @@ -1,6 +1,7 @@ "Reaksiya qoʻyish: %1$s" + "Manzil" "Avatar" "Xabar matni maydonini kichraytirish" "Oʻchirish" @@ -26,9 +27,12 @@ "Pauza" "Ovoz xabar, davomiyligi: %1$s, joriy holati: %2$s" "PIN-kod maydoni" + "Belgilangan joylashuv" "O\'ynang" + "Ijro tezligi" "So\'ro\'vnoma" "So‘rovnoma yakunlandi" + "QR kodi" "%1$s bilan munosabat bildiring" "Boshqa hisbelgilar bilan munosabat bildiring" "%1$s va %2$s bilan oʻqish" @@ -42,9 +46,12 @@ "%1$s bilan reaktsiyani olib tashlang" "Xona avatari" "Fayllarni yuborish" + "Yuboruvchining joylashuvi" "Amal bajarish vaqti cheklangan, tasdiqlash uchun bir daqiqa vaqtingiz bor" "Parolni ko\'rsatish" "Qoʻngʻiroqni boshlash" + "Video chaqiruvni boshlash" + "Ovozli qo‘ng‘iroq qilish" "Arxivlangan xona" "Foydalanuvchi avatari" "Foydalanuvchi menyusi" @@ -56,6 +63,7 @@ "Sizning avataringiz" "Qabul qiling" "Sarlavha qo\'shing" + "Mavjud xonalarni qo‘shish" "Vaqt jadvaliga qo\'shing" "Orqaga" "Qoʻngʻiroq" @@ -75,6 +83,7 @@ "Matnni nusxalash" "Yaratmoq" "Xonani yaratish" + "Maydon yaratish" "Faolsizlantirish" "Hisobni faolsizlantirish" "Rad etish" @@ -91,6 +100,7 @@ "Yoqish" "So‘rovnomani tugatish" "PIN kodni kiriting" + "Jamoat maydonlari o‘rganing" "Tugatish" "Parolni unutdingizmi?" "Oldinga" @@ -111,6 +121,7 @@ "Maydondan chiqish" "Ko\'proq yuklash" "Hisobni boshqarish" + "Hisob va qurilmalarni boshqarish" "Qurilmalarni boshqarish" "Xonalarni boshqarish" "Xabar" @@ -150,18 +161,21 @@ "Ovozli xabar yuborish" "Ulashish" "Havolani ulashing" + "Jonli joylashuvni ulashish" "Koʻrsatish" "Qaytadan kiring" - "Tizimdan chiqish" - "Baribir tizimdan chiqing" + "Bu qurilmani olib tashlash" + "Bu qurilma baribir olib tashlansin" "Oʻtkazib yuborish" "Boshlash" "Suhbatni boshlash" "Qaytadan boshlang" "Tasdiqlashni boshlang" "Xaritani yuklash uchun bosing" + "To‘xtatish" "Rasmga olmoq" "Variantlar uchun bosing" + "Tarjima" "Qayta urinib ko\'ring" "Olib tashlash" "Ko\'rish" @@ -179,6 +193,7 @@ "Kengaytirilgan sozlamalar" "rasm" "Analitika" + "Bildirishnomalar sinxronlanmoqda…" "Siz xonani tark etdingiz" "Siz sessiyadan chiqdingiz" "Ko\'rinish" @@ -191,6 +206,7 @@ "Buferga nusxa koʻchirildi" "Mualliflik huquqi" "Xona yaratilmoqda…" + "Joy yaratilmoqda…" "So\'rov bekor qilindi" "Xonani tark etdi" "Tar etilgan maydon" @@ -211,6 +227,7 @@ "Bo\'sh fayl" "Shifrlash" "Shifrlash yoqilgan" + "Tugaydi: %1$s" "PIN kodini kiriting" "Xato" "Xato yuz berdi, siz yangi xabarlar uchun bildirishnomalarni olmasligingiz mumkin. Iltimos, sozlamalardan bildirishnomalarni bartaraf eting. @@ -237,6 +254,8 @@ Sababi:%1$s." "Satr vaqtinchalik xotiraga nusxalandi" "Havola vaqtinchalik xotiraga nusxalandi" "Yangi qurilmani ulang" + "Jonli joylashuv" + "Jonli joylashuv tugadi" "Yuklanmoqda…" "Batafsil yuklanmoqda…" @@ -263,6 +282,7 @@ Sababi:%1$s." "Oflayn" "Ochiq kodli litsenziyalar" "yoki" + "Boshqa variantlar" "Parol" "Odamlar" "Doimiy havola" @@ -280,8 +300,10 @@ Sababi:%1$s." "Tayyorlanmoqda…" "Maxfiylik siyosati" + "Maxfiy" "Shaxsiy xona" "Shaxsiy guruh" + "Ommaviy" "Jamoat xonasi" "Jamoat guruhi" "Reaktsiya" @@ -289,6 +311,7 @@ Sababi:%1$s." "Sabab" "Qayta tiklash kaliti" "Yangilanmoqda…" + "Olib tashlanmoqda…" "%1$d ta javob" "%1$d ta javob" @@ -298,6 +321,7 @@ Sababi:%1$s." "Muammo haqida xabar bering" "Hisobot topshirildi" "Boy matn muharriri" + "Rol" "Xona" "Xona nomi" "masalan, loyihangiz nomi" @@ -313,6 +337,10 @@ Sababi:%1$s." "Xavfsizlik" "Tomonidan koʻrilgan" "Hisobni tanlang" + + "%1$d ta tanlandi" + "%1$d ta tanlandi" + "Yubirish" "Yuborilmoqda…" "Yuborilmadi" @@ -323,12 +351,15 @@ Sababi:%1$s." "Server URL manzili" "Sozlamalar" "Maydonni ulashish" + "Yangi a’zolar tarixni ko‘radi" + "Ulashilgan jonli joylashuv" "Joylashuvi ulashildi" "Umumiy maydon" - "Chiqish" + "Qurilma olib tashlanmoqda" "Nimadir xato ketdi" "Muammoga duch keldik. Iltimos, qayta urinib koʻring." "Maydon" + "Maydon a’zolari" "Bu maydon nima haqida?" "%1$d Maydon" @@ -337,12 +368,14 @@ Sababi:%1$s." "Chat boshlanmoqda…" "Stiker" "Muvaffaqiyat" + "Tavsiya etilgan" "Tavsiyalar" "Sinxronlash" "Tizim" "Matn" "Uchinchi tomon bildirishnomalari" "Ip" + "Mavzular" "Mavzu" "Bu xona nima haqida?" "Shifrni ochish imkonsiz" @@ -373,14 +406,18 @@ Sababi:%1$s." "Ovozli xabar" "Kutilmoqda…" "Ushbu xabarni kutilmoqda" + "Jonli joylashuv kutilmoqda…" + "Tarixni hamma ko‘rishi mumkin" "Siz" + "%1$s (%2$s) bu xabarni ulashdi, chunki u yuborilganda siz xonada emas edingiz." "Siz yuborgan xabarlar bu xonaga taklif qilingan yangi a’zolarga ulashiladi. %1$s" - "%1$sning shaxsi qayta tiklandi.%2$s" - "%1$sʼning %2$s shaxsiy ma’lumotlari qayta tiklandi.%3$s" + "%1$sning raqamli identifikatori qayta tiklandi.%2$s" + "%1$sning%2$s raqamli identifikatsiya qayta tiklandi.%3$s" "(%1$s )" - "%1$sning shaxsi qayta tiklandi." - "%1$sʼning %2$s shaxsiy ma’lumotlari qayta o‘rnatildi.%3$s" + "%1$s raqamli identifikatori asliga qaytarildi." + "%1$sning%2$s raqamli identifikatsiya qayta tiklandi.%3$s" "Tasdiqlashni bekor qilish" + "Ruxsat berish" "%1$s havolasi sizni boshqa %2$s saytiga olib boradi Davom etasizmi?" @@ -410,6 +447,7 @@ Davom etasizmi?" "%1$sjoylashuvingizga kira olmadi. Iltimos keyinroq qayta urinib ko\'ring." "Ovozli xabaringizni yuklashda xatolik roʻy berdi." "Xona endi mavjud emas yoki taklif yaroqsiz." + "Joylashuvga asoslangan funksiyalardan foydalanish uchun GPS funksiyasini yoqing." "Xabar topilmadi" "%1$sjoylashuvingizga kirishga ruxsati yo\'q. Sozlamalar orqali kirishni yoqishingiz mumkin." "%1$sjoylashuvingizga kirishga ruxsati yo\'q. Quyida kirishni yoqing." @@ -428,6 +466,7 @@ Davom etasizmi?" "Parametrlar" "%1$sni olib tashlash" "Sozlamalar" + "Hech kim joylashuvini ulashmayapti" "Media tanlash jarayonida xatolik yuz berdi, qayta urinib ko\'ring" "Xabarni bosib, bu yerga kiritish uchun \"%1$s\"-ni tanlang." "Muhim xabarlarni osongina topish uchun qadang" @@ -436,11 +475,11 @@ Davom etasizmi?" "%1$d ta qadalgan xabar" "Qadalgan xabarlar" - "Shaxsingizni qayta o‘rnatish uchun %1$s hisobingizga kirishingiz kerak. Shundan so‘ng, avtomatik ravishda ilovaga qaytarilasiz." - "Tasdiqlanmadimi? Shaxsingizni tiklash uchun hisobingizga kiring." + "Raqamli identifikatoringizni tiklash uchun %1$s hisobingizga kirmoqchisiz. Shundan keyin ilovaga qaytarilasiz." + "Tasdiqlay olmayapsizmi? Raqamli identifikatorni tiklash uchun hisobingizga kiring." "Tasdiqlashni olib tashlang va yuboring" "Siz tasdiqlashni bekor qilib, bu xabarni baribir yuborishingiz yoki hozircha to‘xtatib, %1$sʼni qayta tasdiqlagandan so‘ng keyinroq yana urinib ko‘rishingiz mumkin." - "%1$sning tasdiqlangan shaxsiy ma’lumotlari qayta o‘rnatilganligi tufayli xabaringiz jo‘natilmadi" + "Xabaringiz yuborilmadi, chunki %1$sning tasdiqlangan raqamli identifikatori asliga qaytarildi" "Baribir xabar yuborilsin" "%1$s tasdiqlanmagan bir yoki bir nechta qurilmadan foydalanmoqda. Siz xabarni baribir yuborishingiz mumkin yoki hozircha bekor qilib, %2$s barcha qurilmalarini tasdiqlagunga qadar kutib, keyinroq qayta urinishingiz mumkin." "%1$s barcha qurilmalarni tasdiqlamagani uchun xabaringiz yuborilmadi" @@ -452,6 +491,7 @@ Davom etasizmi?" "Xabar %1$sda" "Kengaytirish" "Kamaytirish" + "Jonli joylashuvni ulashish" "Bu xona allaqachon ko‘rilmoqda!" "%1$sʼdan %2$s" "%1$s ta qadalgan xabar" @@ -464,11 +504,15 @@ Davom etasizmi?" "Google Mapsda oching" "OpenStreetMapda oching" "Bu joylashuvni ulashing" + "Ulashish parametrlari" "Siz yaratgan yoki qo‘shilgan maydonlar." "%1$s•%2$s" + "Xonalarni tartibga solish uchun maydon yarating" "%1$s ta maydon" "Maydonlar" - "Xabar yuborilmadi, chunki %1$sʼning tasdiqlangan identifikatori asliga qaytarildi." + "%1$s ulashildi" + "Xaritada" + "Xabar yuborilmadi, chunki%1$s ning tasdiqlangan raqamli identifikatsiyasi qayta tiklandi." "Xabar yuborilmadi, chunki %1$s barcha qurilmalarni tasdiqlamagan." "Xabaringiz yuborilmadi, chunki siz bir yoki bir nechta qurilmangizni tasdiqlamagan ekansiz." "Joylashuv" @@ -478,5 +522,5 @@ Davom etasizmi?" "Tarixiy xabarlarga kirish uchun bu qurilmani tasdiqlashingiz kerak" "Sizni ushbu xabarga ruxsatingiz yoʻq" "Xabarni shifrini ochib bo‘lmadi" - "Bu xabar bloklandi, chunki siz qurilmangizni tasdiqlamadingiz yoki yuboruvchi shaxsingizni tasdiqlashi kerak bo‘lgani sababli bloklandi" + "Qurilmangizni tasdiqlamaganingiz yoki yuboruvchi raqamli shaxsingizni tasdiqlashi kerakligi sababli bu xabar bloklandi." 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 1cc07bb8cf..9a450117ac 100644 --- a/libraries/ui-strings/src/main/res/values-vi/translations.xml +++ b/libraries/ui-strings/src/main/res/values-vi/translations.xml @@ -6,7 +6,7 @@ "Thu nhỏ ô nhập tin nhắn" "Xóa" - "Đã nhập %1$d chữ số" + "%1$d các chữ số đã nhập" "Đổi ảnh đại diện" "Đường dẫn đầy đủ của phòng là %1$s" @@ -47,7 +47,8 @@ "Vị trí người gửi" "Yêu cầu hành động có giới hạn thời gian, bạn có một phút để xác minh" "Hiện mật khẩu" - "Gọi" + "Bắt đầu cuộc gọi" + "Bắt đầu cuộc gọi video" "Bắt đầu cuộc gọi thoại" "Phòng Tombstone" "Ảnh đại diện của người dùng" @@ -270,13 +271,20 @@ Lý do: %1$s ." "Tắt tiếng" "Tên" "Không có kết quả" + "Không có tên phòng" + "Không có tên space" "Không được mã hóa" "Ngoại tuyến" + "Giấy phép mã nguồn mở" "hoặc" + "Các lựa chọn khác" "Mật khẩu" "Danh bạ" "Liên kết cố định" "Quyền truy cập" + "Đã ghim" + "Vui lòng kiểm tra kết nối internet của bạn." + "Vui lòng chờ…" "Bạn có chắc chắn muốn kết thúc cuộc thăm dò này không?" "Khảo sát: %1$s" "Tổng số phiếu: %1$s" @@ -284,20 +292,35 @@ Lý do: %1$s ." "%d lượt bình chọn" + "Đang chuẩn bị…" "Chính sách bảo mật" + "Riêng tư" "Phòng riêng tư" + "Không gian riêng tư" + "Công cộng" + "Phòng công cộng" + "Không gian công cộng" "Biểu cảm" "Cảm xúc" + "Lý do" "Khóa khôi phục." "Đang làm mới…" + "Đang xóa…" + + "%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" + "Vai trò" "Phòng" "Tên phòng" "ví dụ: tên dự án của bạn" + + "%1$d Phòng" + "Đã lưu thay đổi" "Đang lưu" "Khóa màn hình" @@ -305,6 +328,11 @@ Lý do: %1$s ." "Kết quả tìm kiếm" "Bảo mật" "Được xem bởi" + "Chọn tài khoản" + + "%1$d đã chọn" + + "Gửi đến" "Đang gửi…" "Không gửi được" "Đã gửi" @@ -323,6 +351,9 @@ Lý do: %1$s ." "Không gian" "Thành viên không gian" "Không gian này dùng để làm gì?" + + "%1$d Không gian" + "Đang bắt đầu cuộc trò chuyện…" "Sticker" "Thành công" @@ -337,7 +368,9 @@ Lý do: %1$s ." "Chủ đề" "Phòng này dùng để làm gì?" "Không thể giải mã" + "Được gửi từ một thiết bị không an toàn" "Bạn không thể xem tin nhắn này" + "Danh tính kỹ thuật số đã được xác minh của người gửi đã được đặt lại." "Không thể gửi lời mời đến một hoặc nhiều người dùng." "Không thể gửi lời mời" "Mở khóa" @@ -383,6 +416,7 @@ Bạn có chắc muốn tiếp tục không?" "Kích thước tệp tối đa cho phép là: %1$s" "Kích thước tệp quá lớn để tải lên" "Phòng đã được báo cáo" + "Đã báo cáo và rời khỏi phòng." "Xác nhận" "Lỗi" "Thành công" @@ -393,14 +427,23 @@ Bạn có chắc muốn tiếp tục không?" "Kích thước tệp tối đa cho phép là: %1$s" "Chọn chất lượng video bạn muốn tải lên." "Chọn chất lượng tải lên video" + "Tìm kiếm biểu tượng cảm xúc" + "Bạn đã đăng nhập trên thiết bị này với tư cách là%1$s ." + "Máy chủ của bạn cần được nâng cấp để hỗ trợ Dịch vụ Xác thực và tạo tài khoản." "Không tạo được liên kết cố định" "%1$s không thể tải bản đồ. Vui lòng thử lại sau." "Không tải được tin nhắn" "%1$s không thể truy cập vị trí của bạn. Vui lòng thử lại sau." "Không thể tải lên tin nhắn thoại của bạn." + "Phòng đó không còn tồn tại hoặc lời mời không còn hiệu lực." + "Vui lòng bật GPS để truy cập các tính năng dựa trên vị trí." + "Không tìm thấy tin nhắn" "%1$s không có quyền truy cập vị trí của bạn. Bạn có thể bật quyền trong Cài đặt." "%1$s chưa được phép truy cập vị trí. Bật quyền dưới đây." "%1$s không có quyền truy cập micro của bạn. Hãy bật quyền để ghi tin nhắn thoại." + "Nguyên nhân có thể là do sự cố mạng hoặc máy chủ." + "Địa chỉ phòng này đã tồn tại. Vui lòng thử chỉnh sửa trường địa chỉ phòng hoặc thay đổi tên phòng." + "Một số ký tự không được phép. Chỉ các chữ cái, chữ số và các ký hiệu sau được hỗ trợ: ! $ &amp; ' ( ) * + / ; = ? @ [ ] - . _" "Một số tin nhắn chưa được gửi" "Rất tiếc, đã có lỗi xảy ra." "🔐️ Tham gia cùng tôi trên %1$s" @@ -408,6 +451,9 @@ Bạn có chắc muốn tiếp tục không?" "%1$s Android" "Lắc điện thoại để báo cáo lỗi" "Không thể chọn tệp phương tiện. Vui lòng thử lại." + + "%1$d tin nhắn được ghim" + "Tin nhắn được ghim" "Xử lý phương tiện tải lên không thành công, vui lòng thử lại." "Không thể lấy thông tin người dùng" 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 2b12c212a7..11eb111b49 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 @@ -1,6 +1,7 @@ "新增反應:%1$s" + "地址" "大頭貼" "最小化訊息文字欄位" "刪除" @@ -25,9 +26,12 @@ "暫停" "語音訊息,時長:%1$s,目前位置:%2$s" "PIN 碼欄位" + "固定位置" "播放" + "播放速度" "投票" "投票已結束" + "QR Code" "使用 %1$s 回應" "用其他表情符號回應" "%1$s 和 %2$s 已讀" @@ -40,9 +44,12 @@ "移除反應 %1$s" "聊天室大頭照" "傳送檔案" + "傳送者位置" "需要限時動作,您有一分鐘可以驗證" "顯示密碼" "開始通話" + "開始視訊通話" + "開始語音通話" "墓碑聊天室" "使用者大頭照" "使用者選單" @@ -54,6 +61,7 @@ "您的大頭照" "接受" "新增標題" + "新增既有聊天室" "新增至時間軸" "返回" "通話" @@ -73,6 +81,7 @@ "複製文字" "建立" "建立聊天室" + "建立空間" "停用" "停用帳號" "拒絕" @@ -89,6 +98,7 @@ "啟用" "結束投票" "輸入 PIN 碼" + "探索公開空間" "結束" "忘記密碼?" "轉寄" @@ -109,6 +119,7 @@ "離開空間" "載入更多" "管理帳號" + "管理帳號與裝置" "管理裝置" "管理聊天室" "聊天" @@ -148,16 +159,18 @@ "傳送語音訊息" "分享" "分享連結" + "分享即時位置" "顯示" "再登入一次" - "登出" - "直接登出" + "移除此裝置" + "仍要移除此裝置" "略過" "開始" "開始聊天" "重新開始" "開始驗證" "點擊以載入地圖" + "停止" "拍照" "點擊以查看選項" "翻譯" @@ -178,6 +191,7 @@ "進階設定" "影像" "分析" + "正在同步通知……" "您離開聊天室" "您已登出工作階段" "外觀" @@ -190,6 +204,7 @@ "已複製到剪貼簿" "著作權" "正在建立聊天室…" + "正在建立空間……" "請求已取消" "已離開聊天室" "離開空間" @@ -210,6 +225,7 @@ "空檔案" "加密" "已啟用加密" + "結束於 %1$s" "輸入您的 PIN 碼" "錯誤" "發生錯誤,您可能無法收到新訊息的通知。請從設定中進行通知疑難排解。 @@ -235,6 +251,9 @@ "淺色" "行已複製到剪貼簿" "連結已複製到剪貼簿" + "連結新裝置" + "即時位置" + "即時位置已結束" "載入中…" "載入更多……" @@ -245,10 +264,12 @@ "訊息" "訊息動作" + "訊息傳送失敗" "訊息佈局" "訊息已移除" "現代" "關閉通知" + "名稱" "%1$s (%2$s)" "查無結果" "無聊天室名稱" @@ -257,6 +278,7 @@ "離線" "開放原始碼授權條款" "或" + "其他選項" "密碼" "夥伴" "永久連結" @@ -273,8 +295,10 @@ "正在準備……" "隱私權政策" + "私人" "私密聊天室" "私人空間" + "公開" "公開的聊天室" "公開空間" "回應" @@ -282,6 +306,7 @@ "理由" "復原金鑰" "重新整理中…" + "正在移除……" "%1$d 個回覆" @@ -290,9 +315,10 @@ "回報問題" "已遞交報告" "格式化文字編輯器" + "角色" "聊天室" "聊天室名稱" - "範例:您的計畫名稱" + "範例:您的專案名稱" "%1$d 個聊天室" @@ -304,6 +330,9 @@ "安全性" "已讀" "選取帳號" + + "已選取 %1$d 個" + "傳送給" "傳送中…" "傳送失敗" @@ -314,30 +343,36 @@ "伺服器 URL" "設定" "分享空間" + "新成員可以檢視歷史" + "分享即時位置" "位置分享" "共享空間" - "正在登出" + "正在移除裝置" "有錯誤發生" "我們了遇到了問題。請再試一次。" "空間" + "空間成員" + "此空間的用途是?" "%1$d 個空間" "開始聊天…" "貼圖" "成功" + "已建議" "建議" "同步中" "系統" "文字" "第三方通知" "討論串" + "討論串" "主題" - "這個聊天室是做什麼用的?" + "此聊天室的用途是?" "無法解密" "從不安全的裝置傳送" "您無法存取此則訊息" - "傳送者的驗證身份已重設" + "傳送者的驗證數位身份已重設" "無法發送邀請給一或多個使用者。" "無法發送邀請" "解鎖" @@ -362,13 +397,19 @@ "語音訊息" "等待中…" "等待此則訊息" + "正在等待即時位置……" + "任何人都可以檢視歷史" "您" - "%1$s 的身份似乎已重設。%2$s" - "%1$s 的 %2$s 身份似乎已重設。%3$s" + "因為您當時不在聊天室內,所以 %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 的數位身份被重設。" + "%1$s 的 %2$s 數位身份已重設。%3$s" "撤回驗證" + "允許存取" "連結 %1$s 會將您帶往其他網站 %2$s 您確定您想要繼續嗎?" @@ -398,6 +439,7 @@ "%1$s 無法取得您的位置。請稍後再試。" "無法上傳語音訊息。" "此聊天室不再存在或邀請不再有效。" + "請啟用您的 GPS 以存取以位置為基礎的功能。" "找不到訊息" "%1$s 沒有權限存取您的位置。您可以到設定中開啟權限。" "%1$s 沒有權限存取您的位置。請在下方開啟權限。" @@ -423,11 +465,11 @@ "%1$d 則釘選的訊息" "釘選訊息" - "您將要前往您的 %1$s 帳號重設身份。然後您將會被帶回應用程式。" - "無法確認?前往您的帳號以重設您的身份。" + "您將要前往您的 %1$s 帳號重設數位身份。然後您將會被帶回應用程式。" + "無法確認?前往您的帳號以重設您的數位身份。" "撤回驗證並傳送" "您可以撤回您的驗證並仍傳送此訊息,或者您也可以立刻取消並在重新驗證 %1$s 後再試一次。" - "因為 %1$s 的驗證身份已重設,因此未傳送您的訊息。" + "因為 %1$s 的驗證數位身份已重設,因此未傳送您的訊息。" "仍要傳送訊息" "%1$s 正在使用一個或多個未經驗證的裝置。您仍然可以傳送訊息,也可以立刻取消並在 %2$s 驗證其所有裝置後再試一次。" "未傳送您的訊息,因為 %1$s 尚未驗證所有裝置。" @@ -439,6 +481,7 @@ "%1$s 中的訊息" "展開" "減少" + "分享即時位置" "已檢視此聊天室!" "第 %1$s 個,共 %2$s 個" "%1$s 個釘選訊息" @@ -450,12 +493,16 @@ "在 Apple Maps 中開啟" "在 Google Maps 中開啟" "在開放街圖(OpenStreetMap) 中開啟" - "分享這個位置" + "分享選定的位置" + "分享選項" "您建立或加入的空間" "%1$s • %2$s" + "建立空間以整理聊天室" "%1$s 空間" "空間" - "因為 %1$s 的驗證身份已重設,因此未傳送訊息。" + "已分享 %1$s" + "在地圖上" + "因為 %1$s 的驗證數位身份已重設,因此未傳送訊息。" "訊息未傳送,因為 %1$s 尚未驗證所有裝置。" "因為您尚未驗證一個或多個裝置,因此未傳送訊息" "位置" @@ -465,5 +512,5 @@ "您必須驗證此裝置才能存取歷史訊息" "您無法存取此則訊息" "無法解密訊息" - "此訊息被封鎖是因為您沒有驗證您的裝置,或是因為傳送者需要驗證您的身份而被封鎖。" + "此訊息被封鎖,原因可能是您尚未驗證裝置,或是寄件者需要驗證您的數位身分。" 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 1ce3a75ced..15e9fd6bea 100644 --- a/libraries/ui-strings/src/main/res/values-zh/translations.xml +++ b/libraries/ui-strings/src/main/res/values-zh/translations.xml @@ -48,6 +48,7 @@ "限时操作,您有一分钟的时间来验证" "显示密码" "开始通话" + "开始视频通话" "发起语音通话" "已封存的聊天室" "用户头像" @@ -118,6 +119,7 @@ "离开空间" "载入更多" "管理账户" + "管理账户与设备" "管理设备" "管理聊天室" "发送消息给" @@ -168,6 +170,7 @@ "重新开始" "开始验证" "点击以加载地图" + "停止" "拍摄照片" "点按查看选项" "翻译" @@ -188,6 +191,7 @@ "高级设置" "一张图片" "分析" + "正在同步通知…" "你离开了聊天室" "您已退出会话" "外观" @@ -247,6 +251,8 @@ "链接已复制到剪贴板" "链接已复制到剪贴板" "关联新设备" + "实时位置" + "实时位置已结束" "正在加载…" "正在加载更多……" @@ -337,9 +343,10 @@ "设置" "共享空间" "新成员可见历史记录" + "共享实时位置" "共享位置" "共享空间" - "正在登出" + "正在移除设备" "发生了一些错误" "我们遇到了一个问题。请重试。" "空间" @@ -358,6 +365,7 @@ "文本" "第三方通知" "消息列" + "消息列" "主题" "该聊天室的主题是什么?" "无法解密" @@ -388,6 +396,7 @@ "语音消息" "等待…" "正在等待解密密钥" + "正在等待实时位置…" "任何人都可查看历史记录" "您" "%1$s (%2$s) 由于您当时不在聊天室内,系统已将消息共享给您。" @@ -448,8 +457,10 @@ "选项" "移除%1$s" "设置" + "目前无人分享其位置" + "共享实时位置" + "在地图上" "选择媒体失败,请重试。" - "欢迎回来" "按下消息并选择 “%1$s” 将其包含在此处。" "固定重要消息,以便轻松发现它们" diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index f91e3a85b0..ff865de038 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -188,7 +188,7 @@ "About" "Acceptable use policy" "Add an account" - "Add another account" + "Add account" "Adding caption" "Advanced settings" "an image" @@ -467,16 +467,14 @@ Are you sure you want to continue?" "Options" "Remove %1$s" "Settings" + "Nobody is sharing their location" + "Sharing live location" + + "%1$d person" + "%1$d people" + + "On the map" "Failed selecting media, please try again." - "Open Element Classic" - "Open Element Classic on your device" - "Go to Settings > Security & Privacy" - "In Cryptography keys management, select Encrypted messages recovery" - "Follow the instructions to enable your key storage" - "Come back to %1$s" - "Enable your key storage before proceeding to %1$s" - "Checking account" - "Welcome back" "Press on a message and choose “%1$s” to include here." "Pin important messages so that they can be easily discovered" diff --git a/screenshots/html/data.js b/screenshots/html/data.js index df612e28d9..47f9890ad3 100644 --- a/screenshots/html/data.js +++ b/screenshots/html/data.js @@ -1,87 +1,99 @@ // 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",20553,], +["features.preferences.impl.about_AboutView_Day_0_en","features.preferences.impl.about_AboutView_Night_0_en",20563,], ["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",20553,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20553,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20553,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20553,], -["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20553,], -["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20553,], -["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20553,], -["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20553,], -["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20553,], -["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20553,], -["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20553,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_1_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_1_en",20563,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_2_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_2_en",20563,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_3_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_3_en",20563,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_4_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_4_en",20563,], +["features.invite.impl.acceptdecline_AcceptDeclineInviteView_Day_5_en","features.invite.impl.acceptdecline_AcceptDeclineInviteView_Night_5_en",20563,], +["features.logout.impl_AccountDeactivationView_Day_0_en","features.logout.impl_AccountDeactivationView_Night_0_en",20563,], +["features.logout.impl_AccountDeactivationView_Day_1_en","features.logout.impl_AccountDeactivationView_Night_1_en",20563,], +["features.logout.impl_AccountDeactivationView_Day_2_en","features.logout.impl_AccountDeactivationView_Night_2_en",20563,], +["features.logout.impl_AccountDeactivationView_Day_3_en","features.logout.impl_AccountDeactivationView_Night_3_en",20563,], +["features.logout.impl_AccountDeactivationView_Day_4_en","features.logout.impl_AccountDeactivationView_Night_4_en",20563,], +["features.login.impl.accountprovider_AccountProviderOtherView_Day_0_en","features.login.impl.accountprovider_AccountProviderOtherView_Night_0_en",20563,], ["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",20553,], -["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20553,], +["libraries.accountselect.impl_AccountSelectView_Day_0_en","libraries.accountselect.impl_AccountSelectView_Night_0_en",20563,], +["libraries.accountselect.impl_AccountSelectView_Day_1_en","libraries.accountselect.impl_AccountSelectView_Night_1_en",20563,], ["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",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20553,], +["features.messages.impl.actionlist_ActionListViewContent_Day_10_en","features.messages.impl.actionlist_ActionListViewContent_Night_10_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_11_en","features.messages.impl.actionlist_ActionListViewContent_Night_11_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_12_en","features.messages.impl.actionlist_ActionListViewContent_Night_12_en",20563,], ["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",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20553,], -["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20553,], -["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20553,], -["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20553,], -["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20553,], -["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20553,], -["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20553,], -["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20553,], -["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20553,], -["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20553,], +["features.messages.impl.actionlist_ActionListViewContent_Day_2_en","features.messages.impl.actionlist_ActionListViewContent_Night_2_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_3_en","features.messages.impl.actionlist_ActionListViewContent_Night_3_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_4_en","features.messages.impl.actionlist_ActionListViewContent_Night_4_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_5_en","features.messages.impl.actionlist_ActionListViewContent_Night_5_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_6_en","features.messages.impl.actionlist_ActionListViewContent_Night_6_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_7_en","features.messages.impl.actionlist_ActionListViewContent_Night_7_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_8_en","features.messages.impl.actionlist_ActionListViewContent_Night_8_en",20563,], +["features.messages.impl.actionlist_ActionListViewContent_Day_9_en","features.messages.impl.actionlist_ActionListViewContent_Night_9_en",20563,], +["features.createroom.impl.addpeople_AddPeopleView_Day_0_en","features.createroom.impl.addpeople_AddPeopleView_Night_0_en",20563,], +["features.createroom.impl.addpeople_AddPeopleView_Day_1_en","features.createroom.impl.addpeople_AddPeopleView_Night_1_en",20563,], +["features.createroom.impl.addpeople_AddPeopleView_Day_2_en","features.createroom.impl.addpeople_AddPeopleView_Night_2_en",20563,], +["features.createroom.impl.addpeople_AddPeopleView_Day_3_en","features.createroom.impl.addpeople_AddPeopleView_Night_3_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_0_en","features.space.impl.addroom_AddRoomToSpaceView_Night_0_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_1_en","features.space.impl.addroom_AddRoomToSpaceView_Night_1_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_2_en","features.space.impl.addroom_AddRoomToSpaceView_Night_2_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_3_en","features.space.impl.addroom_AddRoomToSpaceView_Night_3_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_4_en","features.space.impl.addroom_AddRoomToSpaceView_Night_4_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_5_en","features.space.impl.addroom_AddRoomToSpaceView_Night_5_en",20563,], +["features.space.impl.addroom_AddRoomToSpaceView_Day_6_en","features.space.impl.addroom_AddRoomToSpaceView_Night_6_en",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_0_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_1_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_2_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_3_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_4_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_5_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_6_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_7_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewBlack_8_en","",0,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_0_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_1_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_2_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_3_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_4_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_5_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_6_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_7_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewDark_8_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_0_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_1_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_2_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_3_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_4_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_5_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_6_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_7_en","",20563,], +["features.preferences.impl.advanced_AdvancedSettingsViewLight_8_en","",20563,], +["libraries.designsystem.components.dialogs_AlertDialogContent_Dialogs_en","",20563,], +["libraries.designsystem.components.dialogs_AlertDialog_Day_0_en","libraries.designsystem.components.dialogs_AlertDialog_Night_0_en",20563,], ["libraries.designsystem.theme.components_AllIcons_Icons_en","",0,], -["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20553,], -["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20553,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20553,], -["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20553,], -["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20553,], +["features.analytics.impl_AnalyticsOptInView_Day_0_en","features.analytics.impl_AnalyticsOptInView_Night_0_en",20563,], +["features.analytics.impl_AnalyticsOptInView_Day_1_en","features.analytics.impl_AnalyticsOptInView_Night_1_en",20563,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_0_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_0_en",20563,], +["features.analytics.api.preferences_AnalyticsPreferencesView_Day_1_en","features.analytics.api.preferences_AnalyticsPreferencesView_Night_1_en",20563,], +["features.preferences.impl.analytics_AnalyticsSettingsView_Day_0_en","features.preferences.impl.analytics_AnalyticsSettingsView_Night_0_en",20563,], ["libraries.designsystem.components_Announcement_Day_0_en","libraries.designsystem.components_Announcement_Night_0_en",0,], -["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20556,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsPage_Night_0_en",0,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_0_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_0_en",0,], +["features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Day_1_en","features.preferences.impl.developer.appsettings_AppDeveloperSettingsView_Night_1_en",0,], +["services.apperror.api_AppErrorView_Day_0_en","services.apperror.api_AppErrorView_Night_0_en",20563,], ["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",20553,], +["libraries.designsystem.components.async_AsyncActionView_Day_1_en","libraries.designsystem.components.async_AsyncActionView_Night_1_en",20563,], ["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",20553,], +["libraries.designsystem.components.async_AsyncActionView_Day_3_en","libraries.designsystem.components.async_AsyncActionView_Night_3_en",20563,], ["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",20553,], +["libraries.designsystem.components.async_AsyncFailure_Day_0_en","libraries.designsystem.components.async_AsyncFailure_Night_0_en",20563,], ["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",20553,], +["features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Day_0_en","features.messages.impl.messagecomposer_AttachmentSourcePickerMenu_Night_0_en",20563,], ["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,], @@ -91,19 +103,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","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20553,], -["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20553,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_0_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_1_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_2_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_3_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_4_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_5_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_6_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_7_en","",20563,], +["features.messages.impl.attachments.preview_AttachmentsPreviewView_8_en","",20563,], ["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",20553,], +["libraries.matrix.ui.components_AvatarActionBottomSheet_Day_0_en","libraries.matrix.ui.components_AvatarActionBottomSheet_Night_0_en",20563,], ["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,], @@ -133,22 +145,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",20553,], +["features.home.impl.components_BatteryOptimizationBanner_Day_0_en","features.home.impl.components_BatteryOptimizationBanner_Night_0_en",20563,], ["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",20553,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20553,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20553,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20553,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20553,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20553,], -["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20553,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_0_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_0_en",20563,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_1_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_1_en",20563,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_2_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_2_en",20563,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_3_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_3_en",20563,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_4_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_4_en",20563,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_5_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_5_en",20563,], +["features.preferences.impl.blockedusers_BlockedUsersView_Day_6_en","features.preferences.impl.blockedusers_BlockedUsersView_Night_6_en",20563,], ["libraries.designsystem.theme.components_BottomSheetDragHandle_Day_0_en","libraries.designsystem.theme.components_BottomSheetDragHandle_Night_0_en",0,], -["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20553,], -["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20553,], -["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20553,], -["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20553,], -["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20553,], +["features.rageshake.impl.bugreport_BugReportViewDay_0_en","",20563,], +["features.rageshake.impl.bugreport_BugReportViewDay_1_en","",20563,], +["features.rageshake.impl.bugreport_BugReportViewDay_2_en","",20563,], +["features.rageshake.impl.bugreport_BugReportViewDay_3_en","",20563,], +["features.rageshake.impl.bugreport_BugReportViewDay_4_en","",20563,], ["features.rageshake.impl.bugreport_BugReportViewNight_0_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_1_en","",0,], ["features.rageshake.impl.bugreport_BugReportViewNight_2_en","",0,], @@ -159,141 +171,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",20553,], -["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20553,], +["features.messages.impl.timeline.components_CallMenuItem_Day_3_en","features.messages.impl.timeline.components_CallMenuItem_Night_3_en",20563,], +["features.messages.impl.timeline.components_CallMenuItem_Day_4_en","features.messages.impl.timeline.components_CallMenuItem_Night_4_en",20563,], ["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",20553,], +["features.messages.impl.timeline.components_CallMenuItem_Day_6_en","features.messages.impl.timeline.components_CallMenuItem_Night_6_en",20563,], ["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",20553,], -["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20553,], -["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20553,], -["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20553,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20553,], -["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20553,], +["features.call.impl.ui_CallScreenView_Day_1_en","features.call.impl.ui_CallScreenView_Night_1_en",20563,], +["features.call.impl.ui_CallScreenView_Day_2_en","features.call.impl.ui_CallScreenView_Night_2_en",20563,], +["features.call.impl.ui_CallScreenView_Day_3_en","features.call.impl.ui_CallScreenView_Night_3_en",20563,], +["libraries.textcomposer_CaptionWarningBottomSheet_Day_0_en","libraries.textcomposer_CaptionWarningBottomSheet_Night_0_en",20563,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_0_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_0_en",20563,], +["features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Day_1_en","features.login.impl.screens.changeaccountprovider_ChangeAccountProviderView_Night_1_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_0_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_0_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_10_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_10_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_11_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_11_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_12_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_12_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_13_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_13_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_1_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_1_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_2_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_2_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_3_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_3_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_4_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_4_en",20563,], ["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",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20553,], -["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20553,], -["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20553,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_6_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_6_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_7_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_7_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_8_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_8_en",20563,], +["features.rolesandpermissions.impl.roles_ChangeRolesView_Day_9_en","features.rolesandpermissions.impl.roles_ChangeRolesView_Night_9_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_0_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_0_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_1_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_1_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_2_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_2_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_3_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_3_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_4_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_4_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_5_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_5_en",20563,], +["features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Day_6_en","features.rolesandpermissions.impl.permissions_ChangeRoomPermissionsView_Night_6_en",20563,], ["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",20553,], -["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20553,], -["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20553,], -["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20553,], -["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20553,], +["features.login.impl.changeserver_ChangeServerView_Day_1_en","features.login.impl.changeserver_ChangeServerView_Night_1_en",20563,], +["features.login.impl.changeserver_ChangeServerView_Day_2_en","features.login.impl.changeserver_ChangeServerView_Night_2_en",20563,], +["features.login.impl.changeserver_ChangeServerView_Day_3_en","features.login.impl.changeserver_ChangeServerView_Night_3_en",20563,], +["features.login.impl.changeserver_ChangeServerView_Day_4_en","features.login.impl.changeserver_ChangeServerView_Night_4_en",20563,], +["features.login.impl.changeserver_ChangeServerView_Day_5_en","features.login.impl.changeserver_ChangeServerView_Night_5_en",20563,], ["libraries.matrix.ui.components_CheckableResolvedUserRow_en","",0,], -["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20553,], +["libraries.matrix.ui.components_CheckableUnresolvedUserRow_en","",20563,], ["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",20553,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20553,], -["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20553,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20553,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20553,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20553,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20553,], -["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20553,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_0_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_0_en",20563,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_1_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_1_en",20563,], +["features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Day_2_en","features.login.impl.screens.chooseaccountprovider_ChooseAccountProviderView_Night_2_en",20563,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_0_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_0_en",20563,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_1_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_1_en",20563,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_2_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_2_en",20563,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_3_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_3_en",20563,], +["features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Day_4_en","features.ftue.impl.sessionverification.choosemode_ChooseSelfVerificationModeView_Night_4_en",20563,], ["libraries.designsystem.theme.components_CircularProgressIndicator_Progress_Indicators_en","",0,], ["libraries.designsystem.components_ClickableLinkText_Text_en","",0,], ["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",20553,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20553,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20553,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20553,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20553,], -["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20553,], -["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20553,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_0_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_0_en",20563,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_1_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_1_en",20563,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_2_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_2_en",20563,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_3_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_3_en",20563,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_4_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_4_en",20563,], +["libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Day_5_en","libraries.designsystem.atomic.molecules_ComposerAlertMolecule_Night_5_en",20563,], +["libraries.textcomposer_ComposerModeView_Day_0_en","libraries.textcomposer_ComposerModeView_Night_0_en",20563,], ["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","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20553,], -["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20553,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20553,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20553,], -["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20553,], -["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20553,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_0_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_1_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_2_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_3_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_4_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_5_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_6_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_7_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewDark_8_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_0_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_1_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_2_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_3_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_4_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_5_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_6_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_7_en","",20563,], +["features.createroom.impl.configureroom_ConfigureRoomViewLight_8_en","",20563,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_0_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_0_en",20563,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_1_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_1_en",20563,], +["features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Day_2_en","features.login.impl.screens.confirmaccountprovider_ConfirmAccountProviderView_Night_2_en",20563,], +["features.home.impl.components_ConfirmRecoveryKeyBanner_Day_0_en","features.home.impl.components_ConfirmRecoveryKeyBanner_Night_0_en",20563,], ["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",20553,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20553,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20553,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20553,], -["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20553,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20553,], -["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20553,], -["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20553,], -["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20553,], -["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20553,], -["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20553,], -["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20553,], -["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20553,], -["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20553,], -["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20553,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20553,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20553,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20553,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20553,], -["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20553,], +["features.rageshake.api.crash_CrashDetectionView_Day_0_en","features.rageshake.api.crash_CrashDetectionView_Night_0_en",20563,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_0_en","features.login.impl.screens.createaccount_CreateAccountView_Night_0_en",20563,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_1_en","features.login.impl.screens.createaccount_CreateAccountView_Night_1_en",20563,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_2_en","features.login.impl.screens.createaccount_CreateAccountView_Night_2_en",20563,], +["features.login.impl.screens.createaccount_CreateAccountView_Day_3_en","features.login.impl.screens.createaccount_CreateAccountView_Night_3_en",20563,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_0_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_0_en",20563,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_1_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_1_en",20563,], +["libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Day_2_en","libraries.matrix.ui.components_CreateDmConfirmationBottomSheet_Night_2_en",0,], +["features.poll.impl.create_CreatePollView_Day_0_en","features.poll.impl.create_CreatePollView_Night_0_en",20563,], +["features.poll.impl.create_CreatePollView_Day_1_en","features.poll.impl.create_CreatePollView_Night_1_en",20563,], +["features.poll.impl.create_CreatePollView_Day_2_en","features.poll.impl.create_CreatePollView_Night_2_en",20563,], +["features.poll.impl.create_CreatePollView_Day_3_en","features.poll.impl.create_CreatePollView_Night_3_en",20563,], +["features.poll.impl.create_CreatePollView_Day_4_en","features.poll.impl.create_CreatePollView_Night_4_en",20563,], +["features.poll.impl.create_CreatePollView_Day_5_en","features.poll.impl.create_CreatePollView_Night_5_en",20563,], +["features.poll.impl.create_CreatePollView_Day_6_en","features.poll.impl.create_CreatePollView_Night_6_en",20563,], +["features.poll.impl.create_CreatePollView_Day_7_en","features.poll.impl.create_CreatePollView_Night_7_en",20563,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_0_en","",20563,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_1_en","",20563,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_2_en","",20563,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_3_en","",20563,], +["libraries.dateformatter.impl.previews_DateFormatterModeView_4_en","",20563,], ["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","",20553,], -["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20553,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20553,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20553,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20553,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20553,], -["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20553,], +["libraries.designsystem.theme.components.previews_DatePickerDark_DateTime_pickers_en","",20563,], +["libraries.designsystem.theme.components.previews_DatePickerLight_DateTime_pickers_en","",20563,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_0_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_0_en",20563,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_1_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_1_en",20563,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_2_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_2_en",20563,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_3_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_3_en",20563,], +["features.invite.impl.declineandblock_DeclineAndBlockView_Day_4_en","features.invite.impl.declineandblock_DeclineAndBlockView_Night_4_en",20563,], ["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",20553,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20553,], -["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20553,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_1_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_1_en",20563,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_2_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_2_en",20563,], +["features.logout.impl.direct_DefaultDirectLogoutView_Day_3_en","features.logout.impl.direct_DefaultDirectLogoutView_Night_3_en",20563,], ["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",20553,], +["features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Day_0_en","features.preferences.impl.notifications.edit_DefaultNotificationSettingOption_Night_0_en",20563,], ["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",20553,], -["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20553,], -["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20553,], -["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20553,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20553,], -["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20553,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20553,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20553,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20553,], -["features.preferences.impl.developer_DeveloperSettingsView_Day_3_en","features.preferences.impl.developer_DeveloperSettingsView_Night_3_en",20553,], +["features.licenses.impl.list_DependencyLicensesListView_Day_0_en","features.licenses.impl.list_DependencyLicensesListView_Night_0_en",20563,], +["features.licenses.impl.list_DependencyLicensesListView_Day_1_en","features.licenses.impl.list_DependencyLicensesListView_Night_1_en",20563,], +["features.licenses.impl.list_DependencyLicensesListView_Day_2_en","features.licenses.impl.list_DependencyLicensesListView_Night_2_en",20563,], +["features.licenses.impl.list_DependencyLicensesListView_Day_3_en","features.licenses.impl.list_DependencyLicensesListView_Night_3_en",20563,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_0_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_0_en",20563,], +["features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Day_1_en","features.linknewdevice.impl.screens.desktop_DesktopNoticeView_Night_1_en",20563,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_0_en","features.preferences.impl.developer_DeveloperSettingsView_Night_0_en",20563,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_1_en","features.preferences.impl.developer_DeveloperSettingsView_Night_1_en",20563,], +["features.preferences.impl.developer_DeveloperSettingsView_Day_2_en","features.preferences.impl.developer_DeveloperSettingsView_Night_2_en",20563,], ["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,], @@ -308,19 +320,20 @@ export const screenshots = [ ["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",20553,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20553,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20553,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20553,], -["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20553,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20553,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20553,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20553,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20553,], -["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20553,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20553,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20553,], -["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20553,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_0_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_0_en",20563,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_1_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_1_en",20563,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_2_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_2_en",20563,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_3_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_3_en",20563,], +["features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Day_4_en","features.preferences.impl.notifications.edit_EditDefaultNotificationSettingView_Night_4_en",20563,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_0_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_0_en",20563,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_1_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_1_en",20563,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_2_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_2_en",20563,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_3_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_3_en",20563,], +["features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Day_4_en","features.securityandprivacy.impl.editroomaddress_EditRoomAddressView_Night_4_en",20563,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_0_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_0_en",20563,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_1_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_1_en",20563,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_2_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_2_en",20563,], +["features.preferences.impl.user.editprofile_EditUserProfileView_Day_3_en","features.preferences.impl.user.editprofile_EditUserProfileView_Night_3_en",0,], ["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,], @@ -328,28 +341,28 @@ 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",20553,], -["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20553,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_0_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_0_en",20563,], +["features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Day_1_en","features.messages.impl.timeline.components.customreaction.picker_EmojiPicker_Night_1_en",20563,], ["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",20553,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20553,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20553,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20553,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20553,], -["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20553,], -["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20553,], -["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20553,], -["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20553,], -["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20553,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_0_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_0_en",20563,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_1_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_1_en",20563,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_2_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_2_en",20563,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_3_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_3_en",20563,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_4_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_4_en",20563,], +["features.linknewdevice.impl.screens.number_EnterNumberView_Day_5_en","features.linknewdevice.impl.screens.number_EnterNumberView_Night_5_en",20563,], +["libraries.designsystem.components.dialogs_ErrorDialogContent_Dialogs_en","",20563,], +["libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialogWithDoNotShowAgain_Night_0_en",20563,], +["libraries.designsystem.components.dialogs_ErrorDialog_Day_0_en","libraries.designsystem.components.dialogs_ErrorDialog_Night_0_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_0_en","features.linknewdevice.impl.screens.error_ErrorView_Night_0_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_1_en","features.linknewdevice.impl.screens.error_ErrorView_Night_1_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_2_en","features.linknewdevice.impl.screens.error_ErrorView_Night_2_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_3_en","features.linknewdevice.impl.screens.error_ErrorView_Night_3_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_4_en","features.linknewdevice.impl.screens.error_ErrorView_Night_4_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_5_en","features.linknewdevice.impl.screens.error_ErrorView_Night_5_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_6_en","features.linknewdevice.impl.screens.error_ErrorView_Night_6_en",20563,], +["features.linknewdevice.impl.screens.error_ErrorView_Day_7_en","features.linknewdevice.impl.screens.error_ErrorView_Night_7_en",20563,], ["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,], @@ -369,47 +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",20553,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20553,], -["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20553,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_1_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_1_en",20563,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_2_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_2_en",20563,], +["features.messages.impl.timeline.focus_FocusRequestStateView_Day_3_en","features.messages.impl.timeline.focus_FocusRequestStateView_Night_3_en",20563,], ["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",20553,], -["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20553,], +["features.forward.impl_ForwardMessagesView_Day_3_en","features.forward.impl_ForwardMessagesView_Night_3_en",20563,], +["features.home.impl.components_FullScreenIntentPermissionBanner_Day_0_en","features.home.impl.components_FullScreenIntentPermissionBanner_Night_0_en",20563,], +["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",0,], ["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",20553,], -["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20553,], -["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20553,], -["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20553,], -["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20553,], +["features.home.impl.spaces_HomeSpacesView_Day_0_en","features.home.impl.spaces_HomeSpacesView_Night_0_en",20563,], +["features.home.impl.spaces_HomeSpacesView_Day_1_en","features.home.impl.spaces_HomeSpacesView_Night_1_en",20563,], +["features.home.impl.spaces_HomeSpacesView_Day_2_en","features.home.impl.spaces_HomeSpacesView_Night_2_en",20563,], +["features.home.impl.components_HomeTopBarMultiAccount_Day_0_en","features.home.impl.components_HomeTopBarMultiAccount_Night_0_en",20563,], +["features.home.impl.components_HomeTopBarSpaceFiltersSelected_Day_0_en","features.home.impl.components_HomeTopBarSpaceFiltersSelected_Night_0_en",20563,], ["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",20553,], -["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20553,], +["features.home.impl.components_HomeTopBarWithIndicator_Day_0_en","features.home.impl.components_HomeTopBarWithIndicator_Night_0_en",20563,], +["features.home.impl.components_HomeTopBar_Day_0_en","features.home.impl.components_HomeTopBar_Night_0_en",20563,], ["features.home.impl_HomeViewA11y_en","",0,], -["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20553,], -["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20553,], +["features.home.impl_HomeView_Day_0_en","features.home.impl_HomeView_Night_0_en",20563,], +["features.home.impl_HomeView_Day_10_en","features.home.impl_HomeView_Night_10_en",20563,], ["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",20553,], -["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20553,], -["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20553,], -["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20553,], -["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20553,], -["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20553,], -["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20553,], -["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20553,], -["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20553,], -["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20553,], -["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20553,], -["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20553,], -["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20553,], +["features.home.impl_HomeView_Day_13_en","features.home.impl_HomeView_Night_13_en",20563,], +["features.home.impl_HomeView_Day_14_en","features.home.impl_HomeView_Night_14_en",20563,], +["features.home.impl_HomeView_Day_15_en","features.home.impl_HomeView_Night_15_en",20563,], +["features.home.impl_HomeView_Day_16_en","features.home.impl_HomeView_Night_16_en",20563,], +["features.home.impl_HomeView_Day_1_en","features.home.impl_HomeView_Night_1_en",20563,], +["features.home.impl_HomeView_Day_2_en","features.home.impl_HomeView_Night_2_en",20563,], +["features.home.impl_HomeView_Day_3_en","features.home.impl_HomeView_Night_3_en",20563,], +["features.home.impl_HomeView_Day_4_en","features.home.impl_HomeView_Night_4_en",20563,], +["features.home.impl_HomeView_Day_5_en","features.home.impl_HomeView_Night_5_en",20563,], +["features.home.impl_HomeView_Day_6_en","features.home.impl_HomeView_Night_6_en",20563,], +["features.home.impl_HomeView_Day_7_en","features.home.impl_HomeView_Night_7_en",20563,], +["features.home.impl_HomeView_Day_8_en","features.home.impl_HomeView_Night_8_en",20563,], +["features.home.impl_HomeView_Day_9_en","features.home.impl_HomeView_Night_9_en",20563,], ["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,], @@ -424,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",20553,], -["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20553,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_1_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_1_en",20563,], +["features.messages.impl.crypto.identity_IdentityChangeStateView_Day_2_en","features.messages.impl.crypto.identity_IdentityChangeStateView_Night_2_en",20563,], ["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,], @@ -433,117 +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",20553,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_4_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_4_en",20563,], ["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",20553,], +["libraries.matrix.ui.messages.reply_InReplyToView_Day_8_en","libraries.matrix.ui.messages.reply_InReplyToView_Night_8_en",20563,], ["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",20553,], -["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20553,], +["features.call.impl.ui_IncomingCallScreen_Day_0_en","features.call.impl.ui_IncomingCallScreen_Night_0_en",20563,], +["features.call.impl.ui_IncomingCallScreen_Day_1_en","features.call.impl.ui_IncomingCallScreen_Night_1_en",20563,], ["features.verifysession.impl.incoming_IncomingVerificationViewA11y_en","",0,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20553,], -["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20553,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_0_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_0_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_10_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_10_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_11_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_11_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_12_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_12_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_13_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_13_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_1_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_1_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_2_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_2_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_3_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_3_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_4_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_4_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_5_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_5_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_6_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_6_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_7_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_7_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_8_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_8_en",20563,], +["features.verifysession.impl.incoming_IncomingVerificationView_Day_9_en","features.verifysession.impl.incoming_IncomingVerificationView_Night_9_en",20563,], ["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",20553,], -["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20553,], -["features.invitepeople.impl_InvitePeopleView_Day_1_en","features.invitepeople.impl_InvitePeopleView_Night_1_en",20553,], +["features.call.impl.ui_InvalidAudioDeviceDialog_Day_0_en","features.call.impl.ui_InvalidAudioDeviceDialog_Night_0_en",20563,], +["features.invitepeople.impl_InvitePeopleView_Day_0_en","features.invitepeople.impl_InvitePeopleView_Night_0_en",20563,], +["features.invitepeople.impl_InvitePeopleView_Day_10_en","features.invitepeople.impl_InvitePeopleView_Night_10_en",0,], +["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",20563,], ["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",20553,], -["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20553,], -["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20553,], -["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20553,], +["features.invitepeople.impl_InvitePeopleView_Day_4_en","features.invitepeople.impl_InvitePeopleView_Night_4_en",20563,], +["features.invitepeople.impl_InvitePeopleView_Day_5_en","features.invitepeople.impl_InvitePeopleView_Night_5_en",20563,], +["features.invitepeople.impl_InvitePeopleView_Day_6_en","features.invitepeople.impl_InvitePeopleView_Night_6_en",20563,], +["features.invitepeople.impl_InvitePeopleView_Day_7_en","features.invitepeople.impl_InvitePeopleView_Night_7_en",20563,], ["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",20553,], -["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20553,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20553,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20553,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20553,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20553,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20553,], -["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20553,], +["features.invitepeople.impl_InvitePeopleView_Day_9_en","features.invitepeople.impl_InvitePeopleView_Night_9_en",20563,], +["libraries.matrix.ui.components_InviteSenderView_Day_0_en","libraries.matrix.ui.components_InviteSenderView_Night_0_en",20563,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_0_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_0_en",20563,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_1_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_1_en",20563,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_2_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_2_en",20563,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_3_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_3_en",20563,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_4_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_4_en",20563,], +["features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Day_5_en","features.startchat.impl.joinbyaddress_JoinRoomByAddressView_Night_5_en",20563,], ["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",20553,], -["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20553,], -["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20553,], -["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20553,], -["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20553,], +["features.joinroom.impl_JoinRoomView_Day_10_en","features.joinroom.impl_JoinRoomView_Night_10_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_11_en","features.joinroom.impl_JoinRoomView_Night_11_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_12_en","features.joinroom.impl_JoinRoomView_Night_12_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_13_en","features.joinroom.impl_JoinRoomView_Night_13_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_14_en","features.joinroom.impl_JoinRoomView_Night_14_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_15_en","features.joinroom.impl_JoinRoomView_Night_15_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_16_en","features.joinroom.impl_JoinRoomView_Night_16_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_1_en","features.joinroom.impl_JoinRoomView_Night_1_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_2_en","features.joinroom.impl_JoinRoomView_Night_2_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_3_en","features.joinroom.impl_JoinRoomView_Night_3_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_4_en","features.joinroom.impl_JoinRoomView_Night_4_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_5_en","features.joinroom.impl_JoinRoomView_Night_5_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_6_en","features.joinroom.impl_JoinRoomView_Night_6_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_7_en","features.joinroom.impl_JoinRoomView_Night_7_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_8_en","features.joinroom.impl_JoinRoomView_Night_8_en",20563,], +["features.joinroom.impl_JoinRoomView_Day_9_en","features.joinroom.impl_JoinRoomView_Night_9_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_0_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_0_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_1_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_1_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_2_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_2_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_3_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_3_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_4_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_4_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_5_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_5_en",20563,], +["features.knockrequests.impl.banner_KnockRequestsBannerView_Day_6_en","features.knockrequests.impl.banner_KnockRequestsBannerView_Night_6_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_0_en","features.knockrequests.impl.list_KnockRequestsListView_Night_0_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_10_en","features.knockrequests.impl.list_KnockRequestsListView_Night_10_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_1_en","features.knockrequests.impl.list_KnockRequestsListView_Night_1_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_2_en","features.knockrequests.impl.list_KnockRequestsListView_Night_2_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_3_en","features.knockrequests.impl.list_KnockRequestsListView_Night_3_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_4_en","features.knockrequests.impl.list_KnockRequestsListView_Night_4_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_5_en","features.knockrequests.impl.list_KnockRequestsListView_Night_5_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_6_en","features.knockrequests.impl.list_KnockRequestsListView_Night_6_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_7_en","features.knockrequests.impl.list_KnockRequestsListView_Night_7_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_8_en","features.knockrequests.impl.list_KnockRequestsListView_Night_8_en",20563,], +["features.knockrequests.impl.list_KnockRequestsListView_Day_9_en","features.knockrequests.impl.list_KnockRequestsListView_Night_9_en",20563,], ["libraries.designsystem.components_LabelledCheckbox_Toggles_en","",0,], -["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20553,], -["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20553,], +["features.preferences.impl.labs_LabsView_Day_0_en","features.preferences.impl.labs_LabsView_Night_0_en",20563,], +["features.preferences.impl.labs_LabsView_Day_1_en","features.preferences.impl.labs_LabsView_Night_1_en",20563,], ["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",20553,], -["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20553,], -["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20553,], -["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20553,], -["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20553,], -["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20553,], -["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20553,], -["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20553,], +["features.leaveroom.impl_LeaveRoomView_Day_1_en","features.leaveroom.impl_LeaveRoomView_Night_1_en",20563,], +["features.leaveroom.impl_LeaveRoomView_Day_2_en","features.leaveroom.impl_LeaveRoomView_Night_2_en",20563,], +["features.leaveroom.impl_LeaveRoomView_Day_3_en","features.leaveroom.impl_LeaveRoomView_Night_3_en",20563,], +["features.leaveroom.impl_LeaveRoomView_Day_4_en","features.leaveroom.impl_LeaveRoomView_Night_4_en",20563,], +["features.leaveroom.impl_LeaveRoomView_Day_5_en","features.leaveroom.impl_LeaveRoomView_Night_5_en",20563,], +["features.leaveroom.impl_LeaveRoomView_Day_6_en","features.leaveroom.impl_LeaveRoomView_Night_6_en",20563,], +["features.leaveroom.impl_LeaveRoomView_Day_7_en","features.leaveroom.impl_LeaveRoomView_Night_7_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_0_en","features.space.impl.leave_LeaveSpaceView_Night_0_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_10_en","features.space.impl.leave_LeaveSpaceView_Night_10_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_1_en","features.space.impl.leave_LeaveSpaceView_Night_1_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_2_en","features.space.impl.leave_LeaveSpaceView_Night_2_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_3_en","features.space.impl.leave_LeaveSpaceView_Night_3_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_4_en","features.space.impl.leave_LeaveSpaceView_Night_4_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_5_en","features.space.impl.leave_LeaveSpaceView_Night_5_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_6_en","features.space.impl.leave_LeaveSpaceView_Night_6_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_7_en","features.space.impl.leave_LeaveSpaceView_Night_7_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_8_en","features.space.impl.leave_LeaveSpaceView_Night_8_en",20563,], +["features.space.impl.leave_LeaveSpaceView_Day_9_en","features.space.impl.leave_LeaveSpaceView_Night_9_en",20563,], ["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",20553,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20553,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20553,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20553,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20553,], -["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20553,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_0_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_0_en",20563,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_1_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_1_en",20563,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_2_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_2_en",20563,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_3_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_3_en",20563,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_4_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_4_en",20563,], +["features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Day_5_en","features.linknewdevice.impl.screens.root_LinkNewDeviceRootView_Night_5_en",20563,], ["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",20553,], +["features.messages.impl.link_LinkView_Day_1_en","features.messages.impl.link_LinkView_Night_1_en",20563,], ["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,], @@ -598,87 +615,107 @@ 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",20553,], +["appnav.room.joined_LoadingRoomNodeView_Day_1_en","appnav.room.joined_LoadingRoomNodeView_Night_1_en",20563,], ["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",20553,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20553,], -["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20553,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_0_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_0_en",20563,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_1_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_1_en",20563,], +["features.lockscreen.impl.settings_LockScreenSettingsView_Day_2_en","features.lockscreen.impl.settings_LockScreenSettingsView_Night_2_en",20563,], ["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",20553,], -["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20553,], -["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20553,], -["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20553,], -["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20553,], -["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20553,], -["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20553,], -["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20553,], -["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20553,], -["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20553,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20553,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20553,], -["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20553,], -["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20553,], -["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20553,], -["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20553,], -["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20553,], -["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20553,], -["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20553,], -["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20553,], -["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20553,], -["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20553,], -["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20553,], -["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20553,], -["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20553,], +["appnav.loggedin_LoggedInView_Day_1_en","appnav.loggedin_LoggedInView_Night_1_en",20563,], +["appnav.loggedin_LoggedInView_Day_2_en","appnav.loggedin_LoggedInView_Night_2_en",20563,], +["appnav.loggedin_LoggedInView_Day_3_en","appnav.loggedin_LoggedInView_Night_3_en",20563,], +["features.login.impl.login_LoginModeView_Day_0_en","features.login.impl.login_LoginModeView_Night_0_en",20563,], +["features.login.impl.login_LoginModeView_Day_1_en","features.login.impl.login_LoginModeView_Night_1_en",20563,], +["features.login.impl.login_LoginModeView_Day_2_en","features.login.impl.login_LoginModeView_Night_2_en",20563,], +["features.login.impl.login_LoginModeView_Day_3_en","features.login.impl.login_LoginModeView_Night_3_en",20563,], +["features.login.impl.login_LoginModeView_Day_4_en","features.login.impl.login_LoginModeView_Night_4_en",20563,], +["features.login.impl.login_LoginModeView_Day_5_en","features.login.impl.login_LoginModeView_Night_5_en",20563,], +["features.login.impl.login_LoginModeView_Day_6_en","features.login.impl.login_LoginModeView_Night_6_en",20563,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_0_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_0_en",20563,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_1_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_1_en",20563,], +["features.login.impl.screens.loginpassword_LoginPasswordView_Day_2_en","features.login.impl.screens.loginpassword_LoginPasswordView_Night_2_en",20563,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_0_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_0_en",0,], +["features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Day_1_en","features.login.impl.screens.classic.loginwithclassic_LoginWithClassicView_Night_1_en",0,], +["features.logout.impl_LogoutView_Day_0_en","features.logout.impl_LogoutView_Night_0_en",20563,], +["features.logout.impl_LogoutView_Day_10_en","features.logout.impl_LogoutView_Night_10_en",20563,], +["features.logout.impl_LogoutView_Day_11_en","features.logout.impl_LogoutView_Night_11_en",20563,], +["features.logout.impl_LogoutView_Day_1_en","features.logout.impl_LogoutView_Night_1_en",20563,], +["features.logout.impl_LogoutView_Day_2_en","features.logout.impl_LogoutView_Night_2_en",20563,], +["features.logout.impl_LogoutView_Day_3_en","features.logout.impl_LogoutView_Night_3_en",20563,], +["features.logout.impl_LogoutView_Day_4_en","features.logout.impl_LogoutView_Night_4_en",20563,], +["features.logout.impl_LogoutView_Day_5_en","features.logout.impl_LogoutView_Night_5_en",20563,], +["features.logout.impl_LogoutView_Day_6_en","features.logout.impl_LogoutView_Night_6_en",20563,], +["features.logout.impl_LogoutView_Day_7_en","features.logout.impl_LogoutView_Night_7_en",20563,], +["features.logout.impl_LogoutView_Day_8_en","features.logout.impl_LogoutView_Night_8_en",20563,], +["features.logout.impl_LogoutView_Day_9_en","features.logout.impl_LogoutView_Night_9_en",20563,], ["libraries.designsystem.components.button_MainActionButton_Buttons_en","",0,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20553,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20553,], -["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20553,], -["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20553,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_0_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_0_en",20563,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_1_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_1_en",20563,], +["features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Day_2_en","features.securityandprivacy.impl.manageauthorizedspaces_ManageAuthorizedSpacesView_Night_2_en",20563,], +["libraries.textcomposer_MarkdownTextComposerEdit_Day_0_en","libraries.textcomposer_MarkdownTextComposerEdit_Night_0_en",20563,], ["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,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutralWrapping_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutralWrapping_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomNeutral_Night_0_en",0,], ["libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Day_0_en","libraries.designsystem.atomic.atoms_MatrixBadgeAtomPositive_Night_0_en",0,], -["libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Day_0_en","libraries.matrix.ui.components_MatrixUserHeaderPlaceholder_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_0_en","libraries.matrix.ui.components_MatrixUserHeader_Night_0_en",0,], ["libraries.matrix.ui.components_MatrixUserHeader_Day_1_en","libraries.matrix.ui.components_MatrixUserHeader_Night_1_en",0,], ["libraries.matrix.ui.components_MatrixUserRow_Day_0_en","libraries.matrix.ui.components_MatrixUserRow_Night_0_en",0,], ["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",20553,], -["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20553,], +["libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDeleteConfirmationBottomSheet_Night_0_en",20563,], +["libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Day_0_en","libraries.mediaviewer.impl.details_MediaDetailsBottomSheet_Night_0_en",20563,], ["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",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20553,], -["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20553,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_0_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_0_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_10_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_10_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_11_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_11_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_12_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_12_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_1_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_1_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_2_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_2_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_3_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_3_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_4_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_4_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_5_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_5_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_6_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_6_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_7_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_7_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_8_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_8_en",20563,], +["libraries.mediaviewer.impl.gallery_MediaGalleryView_Day_9_en","libraries.mediaviewer.impl.gallery_MediaGalleryView_Night_9_en",20563,], ["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,], ["libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Day_2_en","libraries.mediaviewer.impl.local.player_MediaPlayerControllerView_Night_2_en",0,], ["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","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_12_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_13_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_14_en","",0,], +["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_1_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_2_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_3_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_4_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_5_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_6_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_7_en","",0,], +["libraries.mediaviewer.impl.viewer_MediaViewerViewLandscape_8_en","",0,], +["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","",20553,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20553,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_11_en","",20563,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_12_en","",20563,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_13_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20553,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_14_en","",20563,], ["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_1_en","",0,], -["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20553,], +["libraries.mediaviewer.impl.viewer_MediaViewerView_2_en","",20563,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_3_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_4_en","",0,], ["libraries.mediaviewer.impl.viewer_MediaViewerView_5_en","",0,], @@ -692,7 +729,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",20553,], +["features.messages.impl.messagecomposer_MessageComposerView_Day_0_en","features.messages.impl.messagecomposer_MessageComposerView_Night_0_en",20563,], ["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,], @@ -701,7 +738,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",20553,], +["features.messages.impl.timeline.components_MessageShieldView_Day_0_en","features.messages.impl.timeline.components_MessageShieldView_Night_0_en",20563,], ["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,], @@ -710,139 +747,140 @@ 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",20553,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20553,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20553,], -["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20553,], -["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20553,], -["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20553,], -["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20553,], -["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20553,], -["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20553,], -["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20553,], -["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20553,], -["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20553,], -["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20553,], -["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20553,], -["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20553,], +["features.messages.impl.topbars_MessagesViewTopBar_Day_0_en","features.messages.impl.topbars_MessagesViewTopBar_Night_0_en",20563,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_0_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_0_en",20563,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_1_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_1_en",20563,], +["features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Day_2_en","features.messages.impl.crypto.identity_MessagesViewWithIdentityChange_Night_2_en",20563,], +["features.messages.impl_MessagesView_Day_0_en","features.messages.impl_MessagesView_Night_0_en",20563,], +["features.messages.impl_MessagesView_Day_10_en","features.messages.impl_MessagesView_Night_10_en",20563,], +["features.messages.impl_MessagesView_Day_1_en","features.messages.impl_MessagesView_Night_1_en",20563,], +["features.messages.impl_MessagesView_Day_2_en","features.messages.impl_MessagesView_Night_2_en",20563,], +["features.messages.impl_MessagesView_Day_3_en","features.messages.impl_MessagesView_Night_3_en",20563,], +["features.messages.impl_MessagesView_Day_4_en","features.messages.impl_MessagesView_Night_4_en",20563,], +["features.messages.impl_MessagesView_Day_5_en","features.messages.impl_MessagesView_Night_5_en",20563,], +["features.messages.impl_MessagesView_Day_6_en","features.messages.impl_MessagesView_Night_6_en",20563,], +["features.messages.impl_MessagesView_Day_7_en","features.messages.impl_MessagesView_Night_7_en",20563,], +["features.messages.impl_MessagesView_Day_8_en","features.messages.impl_MessagesView_Night_8_en",20563,], +["features.messages.impl_MessagesView_Day_9_en","features.messages.impl_MessagesView_Night_9_en",20563,], ["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",20553,], +["features.migration.impl_MigrationView_Day_1_en","features.migration.impl_MigrationView_Night_1_en",20563,], +["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,], ["appicon.element_MonochromeIcon_en","",0,], -["features.preferences.impl.root_MultiAccountSection_Day_0_en","features.preferences.impl.root_MultiAccountSection_Night_0_en",0,], ["libraries.designsystem.components.dialogs_MultipleSelectionDialogContent_Dialogs_en","",0,], ["libraries.designsystem.components.dialogs_MultipleSelectionDialog_Day_0_en","libraries.designsystem.components.dialogs_MultipleSelectionDialog_Night_0_en",0,], ["libraries.designsystem.components.list_MutipleSelectionListItemSelectedTrailingContent_Multiple_selection_List_item_-_selection_in_trailing_content_List_items_en","",0,], ["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",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20553,], -["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20553,], -["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20553,], +["features.home.impl.components_NewNotificationSoundBanner_Day_0_en","features.home.impl.components_NewNotificationSoundBanner_Night_0_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_0_en","features.preferences.impl.notifications_NotificationSettingsView_Night_0_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_10_en","features.preferences.impl.notifications_NotificationSettingsView_Night_10_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_11_en","features.preferences.impl.notifications_NotificationSettingsView_Night_11_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_12_en","features.preferences.impl.notifications_NotificationSettingsView_Night_12_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_13_en","features.preferences.impl.notifications_NotificationSettingsView_Night_13_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_1_en","features.preferences.impl.notifications_NotificationSettingsView_Night_1_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_2_en","features.preferences.impl.notifications_NotificationSettingsView_Night_2_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_3_en","features.preferences.impl.notifications_NotificationSettingsView_Night_3_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_4_en","features.preferences.impl.notifications_NotificationSettingsView_Night_4_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_5_en","features.preferences.impl.notifications_NotificationSettingsView_Night_5_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_6_en","features.preferences.impl.notifications_NotificationSettingsView_Night_6_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_7_en","features.preferences.impl.notifications_NotificationSettingsView_Night_7_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_8_en","features.preferences.impl.notifications_NotificationSettingsView_Night_8_en",20563,], +["features.preferences.impl.notifications_NotificationSettingsView_Day_9_en","features.preferences.impl.notifications_NotificationSettingsView_Night_9_en",20563,], +["features.ftue.impl.notifications_NotificationsOptInView_Day_0_en","features.ftue.impl.notifications_NotificationsOptInView_Night_0_en",20563,], ["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",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20553,], -["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20553,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_0_en","features.login.impl.screens.onboarding_OnBoardingView_Night_0_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_1_en","features.login.impl.screens.onboarding_OnBoardingView_Night_1_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_2_en","features.login.impl.screens.onboarding_OnBoardingView_Night_2_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_3_en","features.login.impl.screens.onboarding_OnBoardingView_Night_3_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_4_en","features.login.impl.screens.onboarding_OnBoardingView_Night_4_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_5_en","features.login.impl.screens.onboarding_OnBoardingView_Night_5_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_6_en","features.login.impl.screens.onboarding_OnBoardingView_Night_6_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_7_en","features.login.impl.screens.onboarding_OnBoardingView_Night_7_en",20563,], +["features.login.impl.screens.onboarding_OnBoardingView_Day_8_en","features.login.impl.screens.onboarding_OnBoardingView_Night_8_en",0,], ["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",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20553,], +["libraries.matrix.ui.components_OrganizationHeader_Day_0_en","libraries.matrix.ui.components_OrganizationHeader_Night_0_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_0_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_0_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_10_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_10_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_11_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_11_en",20563,], ["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",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20553,], -["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20553,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_1_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_1_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_2_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_2_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_3_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_3_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_4_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_4_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_5_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_5_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_6_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_6_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_7_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_7_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_8_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_8_en",20563,], +["features.verifysession.impl.outgoing_OutgoingVerificationView_Day_9_en","features.verifysession.impl.outgoing_OutgoingVerificationView_Night_9_en",20563,], ["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",20553,], -["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20553,], -["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20553,], -["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20553,], -["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20553,], -["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20553,], +["libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Day_0_en","libraries.mediaviewer.impl.local.pdf_PdfPagesErrorView_Night_0_en",20563,], +["features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Day_0_en","features.rolesandpermissions.impl.roles_PendingMemberRowWithLongName_Night_0_en",20563,], +["libraries.permissions.api_PermissionsView_Day_0_en","libraries.permissions.api_PermissionsView_Night_0_en",20563,], +["libraries.permissions.api_PermissionsView_Day_1_en","libraries.permissions.api_PermissionsView_Night_1_en",20563,], +["libraries.permissions.api_PermissionsView_Day_2_en","libraries.permissions.api_PermissionsView_Night_2_en",20563,], +["libraries.permissions.api_PermissionsView_Day_3_en","libraries.permissions.api_PermissionsView_Night_3_en",20563,], ["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",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20553,], -["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20553,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_0_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_0_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_1_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_1_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_2_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_2_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_3_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_3_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_4_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_4_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_5_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_5_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_6_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_6_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockViewInApp_Day_7_en","features.lockscreen.impl.unlock_PinUnlockViewInApp_Night_7_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_0_en","features.lockscreen.impl.unlock_PinUnlockView_Night_0_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_1_en","features.lockscreen.impl.unlock_PinUnlockView_Night_1_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_2_en","features.lockscreen.impl.unlock_PinUnlockView_Night_2_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_3_en","features.lockscreen.impl.unlock_PinUnlockView_Night_3_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_4_en","features.lockscreen.impl.unlock_PinUnlockView_Night_4_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_5_en","features.lockscreen.impl.unlock_PinUnlockView_Night_5_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_6_en","features.lockscreen.impl.unlock_PinUnlockView_Night_6_en",20563,], +["features.lockscreen.impl.unlock_PinUnlockView_Day_7_en","features.lockscreen.impl.unlock_PinUnlockView_Night_7_en",20563,], ["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",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20553,], -["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20553,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20553,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20553,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20553,], -["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20553,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_10_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_10_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_1_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_1_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_2_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_2_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_3_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_3_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_4_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_4_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_5_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_5_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_6_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_6_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_7_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_7_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_8_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_8_en",20563,], +["features.messages.impl.pinned.banner_PinnedMessagesBannerView_Day_9_en","features.messages.impl.pinned.banner_PinnedMessagesBannerView_Night_9_en",20563,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_0_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_0_en",20563,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_1_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_1_en",20563,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_2_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_2_en",20563,], +["features.messages.impl.pinned.list_PinnedMessagesListView_Day_3_en","features.messages.impl.pinned.list_PinnedMessagesListView_Night_3_en",20563,], ["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",20553,], -["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20553,], -["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20553,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20553,], -["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20553,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedNotSelected_Night_0_en",20563,], +["features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewDisclosedSelected_Night_0_en",20563,], +["features.poll.api.pollcontent_PollAnswerViewEndedSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedSelected_Night_0_en",20563,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerNotSelected_Night_0_en",20563,], +["features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Day_0_en","features.poll.api.pollcontent_PollAnswerViewEndedWinnerSelected_Night_0_en",20563,], ["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",20553,], -["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20553,], -["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20553,], -["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20553,], -["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20553,], -["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20553,], -["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20553,], -["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20553,], -["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20553,], -["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20553,], -["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20553,], +["features.poll.api.pollcontent_PollContentViewCreatorEditable_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEditable_Night_0_en",20563,], +["features.poll.api.pollcontent_PollContentViewCreatorEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewCreatorEnded_Night_0_en",20563,], +["features.poll.api.pollcontent_PollContentViewCreator_Day_0_en","features.poll.api.pollcontent_PollContentViewCreator_Night_0_en",20563,], +["features.poll.api.pollcontent_PollContentViewDisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewDisclosed_Night_0_en",20563,], +["features.poll.api.pollcontent_PollContentViewEnded_Day_0_en","features.poll.api.pollcontent_PollContentViewEnded_Night_0_en",20563,], +["features.poll.api.pollcontent_PollContentViewUndisclosed_Day_0_en","features.poll.api.pollcontent_PollContentViewUndisclosed_Night_0_en",20563,], +["features.poll.impl.history_PollHistoryView_Day_0_en","features.poll.impl.history_PollHistoryView_Night_0_en",20563,], +["features.poll.impl.history_PollHistoryView_Day_1_en","features.poll.impl.history_PollHistoryView_Night_1_en",20563,], +["features.poll.impl.history_PollHistoryView_Day_2_en","features.poll.impl.history_PollHistoryView_Night_2_en",20563,], +["features.poll.impl.history_PollHistoryView_Day_3_en","features.poll.impl.history_PollHistoryView_Night_3_en",20563,], +["features.poll.impl.history_PollHistoryView_Day_4_en","features.poll.impl.history_PollHistoryView_Night_4_en",20563,], ["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,], @@ -856,215 +894,223 @@ 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","",20553,], -["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20553,], -["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20553,], -["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20553,], +["features.preferences.impl.root_PreferencesRootViewDark_0_en","",20563,], +["features.preferences.impl.root_PreferencesRootViewDark_1_en","",20563,], +["features.preferences.impl.root_PreferencesRootViewDark_2_en","",0,], +["features.preferences.impl.root_PreferencesRootViewDark_3_en","",0,], +["features.preferences.impl.root_PreferencesRootViewDark_4_en","",0,], +["features.preferences.impl.root_PreferencesRootViewDark_5_en","",0,], +["features.preferences.impl.root_PreferencesRootViewLight_0_en","",20563,], +["features.preferences.impl.root_PreferencesRootViewLight_1_en","",20563,], +["features.preferences.impl.root_PreferencesRootViewLight_2_en","",0,], +["features.preferences.impl.root_PreferencesRootViewLight_3_en","",0,], +["features.preferences.impl.root_PreferencesRootViewLight_4_en","",0,], +["features.preferences.impl.root_PreferencesRootViewLight_5_en","",0,], ["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","",20553,], -["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20553,], +["libraries.designsystem.components_ProgressDialogContent_Dialogs_en","",20563,], +["libraries.designsystem.components_ProgressDialogWithContent_Day_0_en","libraries.designsystem.components_ProgressDialogWithContent_Night_0_en",20563,], ["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",20553,], -["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20553,], -["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20553,], -["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20553,], -["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20553,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20553,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20553,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20553,], -["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20553,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20553,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20553,], -["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20553,], -["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20553,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20553,], -["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20553,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20553,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20553,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20553,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20553,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20553,], -["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20553,], +["libraries.designsystem.components_ProgressDialog_Day_0_en","libraries.designsystem.components_ProgressDialog_Night_0_en",20563,], +["features.messages.impl.timeline.protection_ProtectedView_Day_0_en","features.messages.impl.timeline.protection_ProtectedView_Night_0_en",20563,], +["features.messages.impl.timeline.protection_ProtectedView_Day_1_en","features.messages.impl.timeline.protection_ProtectedView_Night_1_en",20563,], +["features.messages.impl.timeline.protection_ProtectedView_Day_2_en","features.messages.impl.timeline.protection_ProtectedView_Night_2_en",20563,], +["features.messages.impl.timeline.protection_ProtectedView_Day_3_en","features.messages.impl.timeline.protection_ProtectedView_Night_3_en",20563,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_0_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_0_en",20563,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_1_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_1_en",20563,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_2_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_2_en",20563,], +["libraries.troubleshoot.impl.history_PushHistoryView_Day_3_en","libraries.troubleshoot.impl.history_PushHistoryView_Night_3_en",20563,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_0_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_0_en",20563,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_1_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_1_en",20563,], +["features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Day_2_en","features.login.impl.screens.qrcode.confirmation_QrCodeConfirmationView_Night_2_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_0_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_0_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_1_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_1_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_2_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_2_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_3_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_3_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_4_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_4_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_5_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_5_en",20563,], +["features.login.impl.screens.qrcode.error_QrCodeErrorView_Day_6_en","features.login.impl.screens.qrcode.error_QrCodeErrorView_Night_6_en",20563,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_0_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_0_en",20563,], +["features.login.impl.screens.qrcode.intro_QrCodeIntroView_Day_1_en","features.login.impl.screens.qrcode.intro_QrCodeIntroView_Night_1_en",20563,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_0_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_0_en",20563,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_1_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_1_en",20563,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_2_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_2_en",20563,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_3_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_3_en",20563,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_4_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_4_en",20563,], +["features.login.impl.screens.qrcode.scan_QrCodeScanView_Day_5_en","features.login.impl.screens.qrcode.scan_QrCodeScanView_Night_5_en",20563,], ["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",20553,], -["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20553,], +["features.rageshake.api.detection_RageshakeDialogContent_Day_0_en","features.rageshake.api.detection_RageshakeDialogContent_Night_0_en",20563,], +["features.rageshake.api.preferences_RageshakePreferencesView_Day_0_en","features.rageshake.api.preferences_RageshakePreferencesView_Night_0_en",20563,], ["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",20553,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20553,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20553,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20553,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20553,], -["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20553,], -["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20553,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_0_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_0_en",20563,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_1_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_1_en",20563,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_2_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_2_en",20563,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_3_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_3_en",20563,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_4_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_4_en",20563,], +["features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Day_5_en","features.messages.impl.timeline.components.receipt.bottomsheet_ReadReceiptBottomSheet_Night_5_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_0_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_0_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_10_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_10_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_11_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_11_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_12_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_12_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_13_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_13_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_14_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_14_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_1_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_1_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_2_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_2_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_3_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_3_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_4_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_4_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_5_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_5_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_6_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_6_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_7_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_7_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_8_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_8_en",20563,], +["features.securebackup.impl.setup.views_RecoveryKeyView_Day_9_en","features.securebackup.impl.setup.views_RecoveryKeyView_Night_9_en",20563,], ["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",20553,], -["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20553,], -["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20553,], -["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20553,], -["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20553,], -["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20553,], -["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20553,], -["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20553,], -["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20553,], -["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20553,], -["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20553,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20553,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20553,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20553,], -["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20553,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20553,], -["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20553,], +["features.messages.impl.report_ReportMessageView_Day_0_en","features.messages.impl.report_ReportMessageView_Night_0_en",20563,], +["features.messages.impl.report_ReportMessageView_Day_1_en","features.messages.impl.report_ReportMessageView_Night_1_en",20563,], +["features.messages.impl.report_ReportMessageView_Day_2_en","features.messages.impl.report_ReportMessageView_Night_2_en",20563,], +["features.messages.impl.report_ReportMessageView_Day_3_en","features.messages.impl.report_ReportMessageView_Night_3_en",20563,], +["features.messages.impl.report_ReportMessageView_Day_4_en","features.messages.impl.report_ReportMessageView_Night_4_en",20563,], +["features.messages.impl.report_ReportMessageView_Day_5_en","features.messages.impl.report_ReportMessageView_Night_5_en",20563,], +["features.reportroom.impl_ReportRoomView_Day_0_en","features.reportroom.impl_ReportRoomView_Night_0_en",20563,], +["features.reportroom.impl_ReportRoomView_Day_1_en","features.reportroom.impl_ReportRoomView_Night_1_en",20563,], +["features.reportroom.impl_ReportRoomView_Day_2_en","features.reportroom.impl_ReportRoomView_Night_2_en",20563,], +["features.reportroom.impl_ReportRoomView_Day_3_en","features.reportroom.impl_ReportRoomView_Night_3_en",20563,], +["features.reportroom.impl_ReportRoomView_Day_4_en","features.reportroom.impl_ReportRoomView_Night_4_en",20563,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_0_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_0_en",20563,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_1_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_1_en",20563,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_2_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_2_en",20563,], +["features.securebackup.impl.reset.password_ResetIdentityPasswordView_Day_3_en","features.securebackup.impl.reset.password_ResetIdentityPasswordView_Night_3_en",20563,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_0_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_0_en",20563,], +["features.securebackup.impl.reset.root_ResetIdentityRootView_Day_1_en","features.securebackup.impl.reset.root_ResetIdentityRootView_Night_1_en",20563,], ["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",20553,], -["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20553,], -["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20553,], -["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20553,], -["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20553,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_1_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_1_en",20563,], +["features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Day_2_en","features.messages.impl.crypto.sendfailure.resolve_ResolveVerifiedUserSendFailureView_Night_2_en",20563,], +["libraries.designsystem.components.dialogs_RetryDialogContent_Dialogs_en","",20563,], +["libraries.designsystem.components.dialogs_RetryDialog_Day_0_en","libraries.designsystem.components.dialogs_RetryDialog_Night_0_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_0_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_0_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_1_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_1_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_2_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_2_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_3_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_3_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_4_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_4_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_5_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_5_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_6_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_6_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_7_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_7_en",20563,], +["features.rolesandpermissions.impl.root_RolesAndPermissionsView_Day_8_en","features.rolesandpermissions.impl.root_RolesAndPermissionsView_Night_8_en",20563,], ["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",20553,], -["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20553,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_1_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_1_en",20563,], +["features.roomaliasresolver.impl_RoomAliasResolverView_Day_2_en","features.roomaliasresolver.impl_RoomAliasResolverView_Night_2_en",20563,], ["features.roomdetails.impl_RoomDetailsA11y_en","",0,], -["features.roomdetails.impl_RoomDetailsDark_0_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_10_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_11_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_12_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_13_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_14_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_15_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_16_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_17_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_18_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_19_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_1_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_20_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_21_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_22_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_2_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_3_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_4_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_5_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_6_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_7_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_8_en","",20553,], -["features.roomdetails.impl_RoomDetailsDark_9_en","",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20553,], -["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20553,], -["features.roomdetails.impl_RoomDetails_0_en","",20553,], -["features.roomdetails.impl_RoomDetails_10_en","",20553,], -["features.roomdetails.impl_RoomDetails_11_en","",20553,], -["features.roomdetails.impl_RoomDetails_12_en","",20553,], -["features.roomdetails.impl_RoomDetails_13_en","",20553,], -["features.roomdetails.impl_RoomDetails_14_en","",20553,], -["features.roomdetails.impl_RoomDetails_15_en","",20553,], -["features.roomdetails.impl_RoomDetails_16_en","",20553,], -["features.roomdetails.impl_RoomDetails_17_en","",20553,], -["features.roomdetails.impl_RoomDetails_18_en","",20553,], -["features.roomdetails.impl_RoomDetails_19_en","",20553,], -["features.roomdetails.impl_RoomDetails_1_en","",20553,], -["features.roomdetails.impl_RoomDetails_20_en","",20553,], -["features.roomdetails.impl_RoomDetails_21_en","",20553,], -["features.roomdetails.impl_RoomDetails_22_en","",20553,], -["features.roomdetails.impl_RoomDetails_2_en","",20553,], -["features.roomdetails.impl_RoomDetails_3_en","",20553,], -["features.roomdetails.impl_RoomDetails_4_en","",20553,], -["features.roomdetails.impl_RoomDetails_5_en","",20553,], -["features.roomdetails.impl_RoomDetails_6_en","",20553,], -["features.roomdetails.impl_RoomDetails_7_en","",20553,], -["features.roomdetails.impl_RoomDetails_8_en","",20553,], -["features.roomdetails.impl_RoomDetails_9_en","",20553,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20553,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20553,], -["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20553,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20553,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20553,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20553,], -["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20553,], -["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20553,], -["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20553,], +["features.roomdetails.impl_RoomDetailsDark_0_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_10_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_11_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_12_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_13_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_14_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_15_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_16_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_17_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_18_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_19_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_1_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_20_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_21_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_22_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_2_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_3_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_4_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_5_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_6_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_7_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_8_en","",20563,], +["features.roomdetails.impl_RoomDetailsDark_9_en","",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_0_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_0_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_1_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_1_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_2_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_2_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_3_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_3_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_4_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_4_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_5_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_5_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_6_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_6_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_7_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_7_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_8_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_8_en",20563,], +["features.roomdetailsedit.impl_RoomDetailsEditView_Day_9_en","features.roomdetailsedit.impl_RoomDetailsEditView_Night_9_en",20563,], +["features.roomdetails.impl_RoomDetails_0_en","",20563,], +["features.roomdetails.impl_RoomDetails_10_en","",20563,], +["features.roomdetails.impl_RoomDetails_11_en","",20563,], +["features.roomdetails.impl_RoomDetails_12_en","",20563,], +["features.roomdetails.impl_RoomDetails_13_en","",20563,], +["features.roomdetails.impl_RoomDetails_14_en","",20563,], +["features.roomdetails.impl_RoomDetails_15_en","",20563,], +["features.roomdetails.impl_RoomDetails_16_en","",20563,], +["features.roomdetails.impl_RoomDetails_17_en","",20563,], +["features.roomdetails.impl_RoomDetails_18_en","",20563,], +["features.roomdetails.impl_RoomDetails_19_en","",20563,], +["features.roomdetails.impl_RoomDetails_1_en","",20563,], +["features.roomdetails.impl_RoomDetails_20_en","",20563,], +["features.roomdetails.impl_RoomDetails_21_en","",20563,], +["features.roomdetails.impl_RoomDetails_22_en","",20563,], +["features.roomdetails.impl_RoomDetails_2_en","",20563,], +["features.roomdetails.impl_RoomDetails_3_en","",20563,], +["features.roomdetails.impl_RoomDetails_4_en","",20563,], +["features.roomdetails.impl_RoomDetails_5_en","",20563,], +["features.roomdetails.impl_RoomDetails_6_en","",20563,], +["features.roomdetails.impl_RoomDetails_7_en","",20563,], +["features.roomdetails.impl_RoomDetails_8_en","",20563,], +["features.roomdetails.impl_RoomDetails_9_en","",20563,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_0_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_0_en",20563,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_1_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_1_en",20563,], +["features.roomdirectory.impl.root_RoomDirectoryView_Day_2_en","features.roomdirectory.impl.root_RoomDirectoryView_Night_2_en",20563,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_0_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_0_en",20563,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_1_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_1_en",20563,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_2_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_2_en",20563,], +["features.roomdetails.impl.invite_RoomInviteMembersView_Day_3_en","features.roomdetails.impl.invite_RoomInviteMembersView_Night_3_en",20563,], +["features.home.impl.components_RoomListContentView_Day_0_en","features.home.impl.components_RoomListContentView_Night_0_en",20563,], +["features.home.impl.components_RoomListContentView_Day_1_en","features.home.impl.components_RoomListContentView_Night_1_en",20563,], ["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",20553,], -["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20553,], -["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20553,], -["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20553,], -["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20553,], -["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20553,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20553,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20553,], -["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20553,], +["features.home.impl.components_RoomListContentView_Day_3_en","features.home.impl.components_RoomListContentView_Night_3_en",20563,], +["features.home.impl.components_RoomListContentView_Day_4_en","features.home.impl.components_RoomListContentView_Night_4_en",20563,], +["features.home.impl.components_RoomListContentView_Day_5_en","features.home.impl.components_RoomListContentView_Night_5_en",20563,], +["features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Day_0_en","features.home.impl.roomlist_RoomListDeclineInviteMenuContent_Night_0_en",20563,], +["features.home.impl.filters_RoomListFiltersView_Day_0_en","features.home.impl.filters_RoomListFiltersView_Night_0_en",20563,], +["features.home.impl.filters_RoomListFiltersView_Day_1_en","features.home.impl.filters_RoomListFiltersView_Night_1_en",20563,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_0_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_0_en",20563,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_1_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_1_en",20563,], +["features.home.impl.roomlist_RoomListModalBottomSheetContent_Day_2_en","features.home.impl.roomlist_RoomListModalBottomSheetContent_Night_2_en",20563,], ["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",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20553,], -["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20553,], -["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20553,], +["features.home.impl.search_RoomListSearchContent_Day_1_en","features.home.impl.search_RoomListSearchContent_Night_1_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_0_en","features.roomdetails.impl.members_RoomMemberListView_Night_0_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_1_en","features.roomdetails.impl.members_RoomMemberListView_Night_1_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_2_en","features.roomdetails.impl.members_RoomMemberListView_Night_2_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_3_en","features.roomdetails.impl.members_RoomMemberListView_Night_3_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_4_en","features.roomdetails.impl.members_RoomMemberListView_Night_4_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_5_en","features.roomdetails.impl.members_RoomMemberListView_Night_5_en",20563,], +["features.roomdetails.impl.members_RoomMemberListView_Day_6_en","features.roomdetails.impl.members_RoomMemberListView_Night_6_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_0_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_0_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_1_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_1_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_2_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_2_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_3_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_3_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_4_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_4_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_5_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_5_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_6_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_6_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_7_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_7_en",20563,], +["features.roommembermoderation.impl_RoomMemberModerationView_Day_8_en","features.roommembermoderation.impl_RoomMemberModerationView_Night_8_en",20563,], ["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",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20553,], -["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20553,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsOption_Night_0_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_0_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_1_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_1_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_2_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_2_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_3_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_3_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_4_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_4_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_5_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_5_en",20563,], +["features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Day_6_en","features.roomdetails.impl.notificationsettings_RoomNotificationSettingsView_Night_6_en",20563,], ["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",20553,], -["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20553,], -["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20553,], -["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20553,], -["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20553,], -["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20553,], +["libraries.roomselect.impl_RoomSelectView_Day_0_en","libraries.roomselect.impl_RoomSelectView_Night_0_en",20563,], +["libraries.roomselect.impl_RoomSelectView_Day_1_en","libraries.roomselect.impl_RoomSelectView_Night_1_en",20563,], +["libraries.roomselect.impl_RoomSelectView_Day_2_en","libraries.roomselect.impl_RoomSelectView_Night_2_en",20563,], +["libraries.roomselect.impl_RoomSelectView_Day_3_en","libraries.roomselect.impl_RoomSelectView_Night_3_en",20563,], +["libraries.roomselect.impl_RoomSelectView_Day_4_en","libraries.roomselect.impl_RoomSelectView_Night_4_en",20563,], +["libraries.roomselect.impl_RoomSelectView_Day_5_en","libraries.roomselect.impl_RoomSelectView_Night_5_en",20563,], ["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,], @@ -1087,16 +1133,17 @@ 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",20553,], -["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20553,], -["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20553,], -["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20553,], -["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20553,], -["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20553,], -["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20553,], -["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20553,], +["features.home.impl.components_RoomSummaryRow_Day_29_en","features.home.impl.components_RoomSummaryRow_Night_29_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_2_en","features.home.impl.components_RoomSummaryRow_Night_2_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_30_en","features.home.impl.components_RoomSummaryRow_Night_30_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_31_en","features.home.impl.components_RoomSummaryRow_Night_31_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_32_en","features.home.impl.components_RoomSummaryRow_Night_32_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_33_en","features.home.impl.components_RoomSummaryRow_Night_33_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_34_en","features.home.impl.components_RoomSummaryRow_Night_34_en",20563,], +["features.home.impl.components_RoomSummaryRow_Day_35_en","features.home.impl.components_RoomSummaryRow_Night_35_en",20563,], ["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",20553,], +["features.home.impl.components_RoomSummaryRow_Day_37_en","features.home.impl.components_RoomSummaryRow_Night_37_en",20563,], +["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,], ["features.home.impl.components_RoomSummaryRow_Day_5_en","features.home.impl.components_RoomSummaryRow_Night_5_en",0,], @@ -1104,118 +1151,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",20553,], -["appnav.root_RootView_Day_1_en","appnav.root_RootView_Night_1_en",20553,], -["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20553,], +["appnav.root_RootView_Day_0_en","appnav.root_RootView_Night_0_en",20563,], +["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",20563,], +["appnav.root_RootView_Day_2_en","appnav.root_RootView_Night_2_en",20563,], ["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",20553,], -["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20553,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20553,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20553,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20553,], -["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20553,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20553,], -["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20553,], +["features.verifysession.impl.emoji_SasEmojis_Day_0_en","features.verifysession.impl.emoji_SasEmojis_Night_0_en",20563,], +["libraries.designsystem.components.dialogs_SaveChangesDialog_Day_0_en","libraries.designsystem.components.dialogs_SaveChangesDialog_Night_0_en",20563,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_0_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_0_en",20563,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_1_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_1_en",20563,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_2_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_2_en",20563,], +["features.linknewdevice.impl.screens.scan_ScanQrCodeView_Day_3_en","features.linknewdevice.impl.screens.scan_ScanQrCodeView_Night_3_en",20563,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_0_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_0_en",20563,], +["features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Day_1_en","features.login.impl.screens.searchaccountprovider_SearchAccountProviderView_Night_1_en",20563,], ["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","",20553,], +["libraries.designsystem.theme.components_SearchBarActiveWithNoResults_Search_views_en","",20563,], ["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","",20553,], -["features.startchat.impl.components_SearchSingleUserResultItem_en","",20553,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20553,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20553,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20553,], -["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20553,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20553,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20553,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20553,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20553,], -["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20553,], -["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20553,], -["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20553,], -["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20553,], -["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20553,], +["features.startchat.impl.components_SearchMultipleUsersResultItem_en","",20563,], +["features.startchat.impl.components_SearchSingleUserResultItem_en","",20563,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_0_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_0_en",20563,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_1_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_1_en",20563,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_2_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_2_en",20563,], +["features.securebackup.impl.disable_SecureBackupDisableView_Day_3_en","features.securebackup.impl.disable_SecureBackupDisableView_Night_3_en",20563,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_0_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_0_en",20563,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_1_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_1_en",20563,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_2_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_2_en",20563,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_3_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_3_en",20563,], +["features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Day_4_en","features.securebackup.impl.enter_SecureBackupEnterRecoveryKeyView_Night_4_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_0_en","features.securebackup.impl.root_SecureBackupRootView_Night_0_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_10_en","features.securebackup.impl.root_SecureBackupRootView_Night_10_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_11_en","features.securebackup.impl.root_SecureBackupRootView_Night_11_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_12_en","features.securebackup.impl.root_SecureBackupRootView_Night_12_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_13_en","features.securebackup.impl.root_SecureBackupRootView_Night_13_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_14_en","features.securebackup.impl.root_SecureBackupRootView_Night_14_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_15_en","features.securebackup.impl.root_SecureBackupRootView_Night_15_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_16_en","features.securebackup.impl.root_SecureBackupRootView_Night_16_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_17_en","features.securebackup.impl.root_SecureBackupRootView_Night_17_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_1_en","features.securebackup.impl.root_SecureBackupRootView_Night_1_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_2_en","features.securebackup.impl.root_SecureBackupRootView_Night_2_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_3_en","features.securebackup.impl.root_SecureBackupRootView_Night_3_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_4_en","features.securebackup.impl.root_SecureBackupRootView_Night_4_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_5_en","features.securebackup.impl.root_SecureBackupRootView_Night_5_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_6_en","features.securebackup.impl.root_SecureBackupRootView_Night_6_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_7_en","features.securebackup.impl.root_SecureBackupRootView_Night_7_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_8_en","features.securebackup.impl.root_SecureBackupRootView_Night_8_en",20563,], +["features.securebackup.impl.root_SecureBackupRootView_Day_9_en","features.securebackup.impl.root_SecureBackupRootView_Night_9_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_0_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_1_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_2_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_3_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_4_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupViewChange_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupViewChange_Night_5_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_0_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_0_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_1_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_1_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_2_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_2_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_3_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_3_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_4_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_4_en",20563,], +["features.securebackup.impl.setup_SecureBackupSetupView_Day_5_en","features.securebackup.impl.setup_SecureBackupSetupView_Night_5_en",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_0_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_10_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_11_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_12_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_13_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_14_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_15_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_16_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_17_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_18_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_19_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_1_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_20_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_21_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_22_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_23_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_2_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_3_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_4_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_5_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_6_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_7_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_8_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewDark_9_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_0_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_10_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_11_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_12_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_13_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_14_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_15_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_16_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_17_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_18_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_19_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_1_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_20_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_21_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_22_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_23_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_2_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_3_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_4_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_5_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_6_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_7_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_8_en","",20563,], +["features.securityandprivacy.impl.root_SecurityAndPrivacyViewLight_9_en","",20563,], +["features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Day_0_en","features.createroom.impl.configureroom_SelectParentSpaceBottomSheet_Night_0_en",20563,], ["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,], @@ -1238,33 +1286,33 @@ 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",20553,], -["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20553,], -["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20553,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20553,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20553,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20553,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20553,], -["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20553,], -["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20553,], -["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20553,], -["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20553,], -["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20553,], -["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20553,], -["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20553,], -["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20553,], +["features.verifysession.impl.incoming.ui_SessionDetailsView_Day_0_en","features.verifysession.impl.incoming.ui_SessionDetailsView_Night_0_en",20563,], +["features.home.impl.components_SetUpRecoveryKeyBanner_Day_0_en","features.home.impl.components_SetUpRecoveryKeyBanner_Night_0_en",20563,], +["features.lockscreen.impl.setup.biometric_SetupBiometricView_Day_0_en","features.lockscreen.impl.setup.biometric_SetupBiometricView_Night_0_en",20563,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_0_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_0_en",20563,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_1_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_1_en",20563,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_2_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_2_en",20563,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_3_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_3_en",20563,], +["features.lockscreen.impl.setup.pin_SetupPinView_Day_4_en","features.lockscreen.impl.setup.pin_SetupPinView_Night_4_en",20563,], +["features.location.impl.share_ShareLocationView_Day_0_en","features.location.impl.share_ShareLocationView_Night_0_en",20563,], +["features.location.impl.share_ShareLocationView_Day_1_en","features.location.impl.share_ShareLocationView_Night_1_en",20563,], +["features.location.impl.share_ShareLocationView_Day_2_en","features.location.impl.share_ShareLocationView_Night_2_en",20563,], +["features.location.impl.share_ShareLocationView_Day_3_en","features.location.impl.share_ShareLocationView_Night_3_en",20563,], +["features.location.impl.share_ShareLocationView_Day_4_en","features.location.impl.share_ShareLocationView_Night_4_en",20563,], +["features.location.impl.share_ShareLocationView_Day_5_en","features.location.impl.share_ShareLocationView_Night_5_en",20563,], +["features.location.impl.share_ShareLocationView_Day_6_en","features.location.impl.share_ShareLocationView_Night_6_en",20563,], ["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",20553,], -["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20553,], -["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20553,], -["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20553,], -["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20553,], -["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20553,], -["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20553,], -["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20553,], -["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20553,], +["features.share.impl_ShareView_Day_3_en","features.share.impl_ShareView_Night_3_en",20563,], +["features.location.impl.show_ShowLocationView_Day_0_en","features.location.impl.show_ShowLocationView_Night_0_en",20563,], +["features.location.impl.show_ShowLocationView_Day_1_en","features.location.impl.show_ShowLocationView_Night_1_en",20563,], +["features.location.impl.show_ShowLocationView_Day_2_en","features.location.impl.show_ShowLocationView_Night_2_en",20563,], +["features.location.impl.show_ShowLocationView_Day_3_en","features.location.impl.show_ShowLocationView_Night_3_en",20563,], +["features.location.impl.show_ShowLocationView_Day_4_en","features.location.impl.show_ShowLocationView_Night_4_en",20563,], +["features.location.impl.show_ShowLocationView_Day_5_en","features.location.impl.show_ShowLocationView_Night_5_en",20563,], +["features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Day_0_en","features.linknewdevice.impl.screens.qrcode_ShowQrCodeView_Night_0_en",20563,], +["features.signedout.impl_SignedOutView_Day_0_en","features.signedout.impl_SignedOutView_Night_0_en",20563,], ["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,], @@ -1274,107 +1322,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",20553,], +["features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Day_0_en","features.login.impl.dialogs_SlidingSyncNotSupportedDialog_Night_0_en",20563,], ["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,], -["features.announcement.impl.spaces_SpaceAnnouncementView_Day_0_en","features.announcement.impl.spaces_SpaceAnnouncementView_Night_0_en",20553,], ["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",20553,], -["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20553,], -["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20553,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_0_en","features.home.impl.spacefilters_SpaceFiltersView_Night_0_en",20563,], +["features.home.impl.spacefilters_SpaceFiltersView_Day_1_en","features.home.impl.spacefilters_SpaceFiltersView_Night_1_en",20563,], +["libraries.matrix.ui.components_SpaceHeaderRootView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderRootView_Night_0_en",20563,], ["libraries.matrix.ui.components_SpaceHeaderView_Day_0_en","libraries.matrix.ui.components_SpaceHeaderView_Night_0_en",0,], -["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20553,], +["libraries.matrix.ui.components_SpaceInfoRow_Day_0_en","libraries.matrix.ui.components_SpaceInfoRow_Night_0_en",20563,], ["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",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20553,], -["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20553,], -["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20553,], -["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20553,], -["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20553,], -["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20553,], -["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20553,], -["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20553,], -["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20553,], -["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20553,], -["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20553,], -["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20553,], -["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20553,], -["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20553,], -["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20553,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_0_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_0_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_1_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_1_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_2_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_2_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_3_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_3_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_4_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_4_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_5_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_5_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_6_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_6_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_7_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_7_en",20563,], +["libraries.matrix.ui.components_SpaceRoomItemView_Day_8_en","libraries.matrix.ui.components_SpaceRoomItemView_Night_8_en",20563,], +["features.space.impl.settings_SpaceSettingsView_Day_0_en","features.space.impl.settings_SpaceSettingsView_Night_0_en",20563,], +["features.space.impl.settings_SpaceSettingsView_Day_1_en","features.space.impl.settings_SpaceSettingsView_Night_1_en",20563,], +["features.space.impl.settings_SpaceSettingsView_Day_2_en","features.space.impl.settings_SpaceSettingsView_Night_2_en",20563,], +["features.space.impl.settings_SpaceSettingsView_Day_3_en","features.space.impl.settings_SpaceSettingsView_Night_3_en",20563,], +["features.space.impl.root_SpaceView_Day_0_en","features.space.impl.root_SpaceView_Night_0_en",20563,], +["features.space.impl.root_SpaceView_Day_1_en","features.space.impl.root_SpaceView_Night_1_en",20563,], +["features.space.impl.root_SpaceView_Day_2_en","features.space.impl.root_SpaceView_Night_2_en",20563,], +["features.space.impl.root_SpaceView_Day_3_en","features.space.impl.root_SpaceView_Night_3_en",20563,], +["features.space.impl.root_SpaceView_Day_4_en","features.space.impl.root_SpaceView_Night_4_en",20563,], +["features.space.impl.root_SpaceView_Day_5_en","features.space.impl.root_SpaceView_Night_5_en",20563,], +["features.space.impl.root_SpaceView_Day_6_en","features.space.impl.root_SpaceView_Night_6_en",20563,], +["features.space.impl.root_SpaceView_Day_7_en","features.space.impl.root_SpaceView_Night_7_en",20563,], +["features.space.impl.root_SpaceView_Day_8_en","features.space.impl.root_SpaceView_Night_8_en",20563,], ["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",20553,], -["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20553,], -["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20553,], -["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20553,], -["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20553,], -["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20553,], -["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20553,], +["features.startchat.impl.root_StartChatView_Day_0_en","features.startchat.impl.root_StartChatView_Night_0_en",20563,], +["features.startchat.impl.root_StartChatView_Day_1_en","features.startchat.impl.root_StartChatView_Night_1_en",20563,], +["features.startchat.impl.root_StartChatView_Day_2_en","features.startchat.impl.root_StartChatView_Night_2_en",20563,], +["features.startchat.impl.root_StartChatView_Day_3_en","features.startchat.impl.root_StartChatView_Night_3_en",20563,], +["features.startchat.impl.root_StartChatView_Day_4_en","features.startchat.impl.root_StartChatView_Night_4_en",20563,], +["features.startchat.impl.root_StartChatView_Day_5_en","features.startchat.impl.root_StartChatView_Night_5_en",20563,], +["features.location.api.internal_StaticMapPlaceholder_Day_0_en","features.location.api.internal_StaticMapPlaceholder_Night_0_en",20563,], ["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",20553,], +["features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Day_0_en","features.messages.impl.messagecomposer.suggestions_SuggestionsPickerView_Night_0_en",20563,], ["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",20553,], +["appnav.loggedin_SyncStateView_Day_0_en","appnav.loggedin_SyncStateView_Night_0_en",20563,], ["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",20553,], -["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20553,], -["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20553,], -["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20553,], -["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20553,], -["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20553,], -["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20553,], -["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20553,], -["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20553,], -["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20553,], -["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20553,], -["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20553,], -["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20553,], -["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20553,], -["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20553,], +["libraries.textcomposer_TextComposerAddCaption_Day_0_en","libraries.textcomposer_TextComposerAddCaption_Night_0_en",20563,], +["libraries.textcomposer_TextComposerCaption_Day_0_en","libraries.textcomposer_TextComposerCaption_Night_0_en",20563,], +["libraries.textcomposer_TextComposerEditCaption_Day_0_en","libraries.textcomposer_TextComposerEditCaption_Night_0_en",20563,], +["libraries.textcomposer_TextComposerEditNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerEditNotEncrypted_Night_0_en",20563,], +["libraries.textcomposer_TextComposerEdit_Day_0_en","libraries.textcomposer_TextComposerEdit_Night_0_en",20563,], +["libraries.textcomposer_TextComposerFormattingNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerFormattingNotEncrypted_Night_0_en",20563,], +["libraries.textcomposer_TextComposerFormatting_Day_0_en","libraries.textcomposer_TextComposerFormatting_Night_0_en",20563,], +["libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLinkWithoutText_Night_0_en",20563,], +["libraries.textcomposer_TextComposerLinkDialogCreateLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogCreateLink_Night_0_en",20563,], +["libraries.textcomposer_TextComposerLinkDialogEditLink_Day_0_en","libraries.textcomposer_TextComposerLinkDialogEditLink_Night_0_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_0_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_10_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_10_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_11_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_11_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_1_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_1_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_2_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_2_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_3_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_3_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_4_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_4_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_5_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_5_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_6_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_6_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_7_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_7_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_8_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_8_en",20563,], +["libraries.textcomposer_TextComposerReplyNotEncrypted_Day_9_en","libraries.textcomposer_TextComposerReplyNotEncrypted_Night_9_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_0_en","libraries.textcomposer_TextComposerReply_Night_0_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_10_en","libraries.textcomposer_TextComposerReply_Night_10_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_11_en","libraries.textcomposer_TextComposerReply_Night_11_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_1_en","libraries.textcomposer_TextComposerReply_Night_1_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_2_en","libraries.textcomposer_TextComposerReply_Night_2_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_3_en","libraries.textcomposer_TextComposerReply_Night_3_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_4_en","libraries.textcomposer_TextComposerReply_Night_4_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_5_en","libraries.textcomposer_TextComposerReply_Night_5_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_6_en","libraries.textcomposer_TextComposerReply_Night_6_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_7_en","libraries.textcomposer_TextComposerReply_Night_7_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_8_en","libraries.textcomposer_TextComposerReply_Night_8_en",20563,], +["libraries.textcomposer_TextComposerReply_Day_9_en","libraries.textcomposer_TextComposerReply_Night_9_en",20563,], +["libraries.textcomposer_TextComposerSimpleNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerSimpleNotEncrypted_Night_0_en",20563,], +["libraries.textcomposer_TextComposerSimple_Day_0_en","libraries.textcomposer_TextComposerSimple_Night_0_en",20563,], +["libraries.textcomposer_TextComposerVoiceNotEncrypted_Day_0_en","libraries.textcomposer_TextComposerVoiceNotEncrypted_Night_0_en",20563,], ["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",20553,], -["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20553,], +["libraries.designsystem.components.dialogs_TextFieldDialogWithError_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialogWithError_Night_0_en",20563,], +["libraries.designsystem.components.dialogs_TextFieldDialog_Day_0_en","libraries.designsystem.components.dialogs_TextFieldDialog_Night_0_en",20563,], ["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,], @@ -1386,16 +1433,18 @@ export const screenshots = [ ["libraries.mediaviewer.impl.local.txt_TextFileContentView_Day_3_en","libraries.mediaviewer.impl.local.txt_TextFileContentView_Night_3_en",0,], ["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.timeline.components_ThreadSummaryView_Day_0_en","features.messages.impl.timeline.components_ThreadSummaryView_Night_0_en",20553,], -["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20553,], -["libraries.designsystem.theme.components.previews_TimePickerHorizontal_DateTime_pickers_en","",20553,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20553,], -["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20553,], +["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",20563,], +["features.messages.impl.topbars_ThreadTopBar_Day_0_en","features.messages.impl.topbars_ThreadTopBar_Night_0_en",20563,], +["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","",20563,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalDark_DateTime_pickers_en","",20563,], +["libraries.designsystem.theme.components.previews_TimePickerVerticalLight_DateTime_pickers_en","",20563,], ["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",20553,], -["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20553,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_3_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_3_en",20563,], +["features.messages.impl.timeline.components_TimelineEventTimestampView_Day_4_en","features.messages.impl.timeline.components_TimelineEventTimestampView_Night_4_en",20563,], ["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,], @@ -1405,18 +1454,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",20553,], +["features.messages.impl.timeline.components_TimelineItemCallNotifyView_Day_0_en","features.messages.impl.timeline.components_TimelineItemCallNotifyView_Night_0_en",20563,], ["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",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20553,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_0_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_1_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_2_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_3_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_4_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_4_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_5_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_5_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_6_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_6_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_7_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_7_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Day_8_en","features.messages.impl.timeline.components.event_TimelineItemEncryptedView_Night_8_en",20563,], ["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,], @@ -1424,18 +1473,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",20553,], -["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20553,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_3_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_3_en",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_4_en",20563,], ["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",20553,], -["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20553,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20553,], +["features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Day_7_en","features.messages.impl.timeline.components_TimelineItemEventRowTimestamp_Night_7_en",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowUtd_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowUtd_Night_0_en",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithManyReactions_Night_0_en",20563,], ["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",20553,], -["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20553,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_0_en",20563,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Day_1_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReplyInformative_Night_1_en",20563,], ["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,], @@ -1444,42 +1493,42 @@ 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",20553,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_4_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_4_en",20563,], ["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",20553,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Day_8_en","features.messages.impl.timeline.components_TimelineItemEventRowWithReply_Night_8_en",20563,], ["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",20553,], +["features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Day_0_en","features.messages.impl.timeline.components_TimelineItemEventRowWithThreadSummary_Night_0_en",20563,], ["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","",20553,], +["features.messages.impl.timeline.components_TimelineItemEventTimestampBelow_en","",20563,], ["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",20553,], -["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20553,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentCollapse_Night_0_en",20563,], +["features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Day_0_en","features.messages.impl.timeline.components_TimelineItemGroupedEventsRowContentExpanded_Night_0_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemImageViewHideMediaContent_Night_0_en",20563,], ["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",20553,], +["features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemLegacyCallInviteView_Night_0_en",20563,], ["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",0,], ["features.messages.impl.timeline.components.event_TimelineItemLocationView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemLocationView_Night_2_en",0,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20553,], -["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20553,], -["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20553,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_0_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_1_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_1_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_2_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_2_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemPollView_Day_3_en","features.messages.impl.timeline.components.event_TimelineItemPollView_Night_3_en",20563,], +["features.messages.impl.timeline.components_TimelineItemReactionsLayout_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsLayout_Night_0_en",20563,], ["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",20553,], -["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20553,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewIncoming_Night_0_en",20563,], +["features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Day_0_en","features.messages.impl.timeline.components_TimelineItemReactionsViewOutgoing_Night_0_en",20563,], ["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",20553,], +["features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemReadMarkerView_Night_0_en",20563,], ["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,], @@ -1488,8 +1537,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",20553,], -["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20553,], +["features.messages.impl.timeline.components.event_TimelineItemRedactedView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemRedactedView_Night_0_en",20563,], +["features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Day_0_en","features.messages.impl.timeline.components.virtual_TimelineItemRoomBeginningView_Night_0_en",20563,], ["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,], @@ -1504,8 +1553,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",20553,], -["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20553,], +["features.messages.impl.timeline.components.event_TimelineItemUnknownView_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemUnknownView_Night_0_en",20563,], +["features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Day_0_en","features.messages.impl.timeline.components.event_TimelineItemVideoViewHideMediaContent_Night_0_en",20563,], ["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,], @@ -1528,85 +1577,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",20553,], -["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20553,], -["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20553,], +["features.messages.impl.timeline_TimelineViewMessageShield_Day_0_en","features.messages.impl.timeline_TimelineViewMessageShield_Night_0_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_0_en","features.messages.impl.timeline_TimelineView_Night_0_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_10_en","features.messages.impl.timeline_TimelineView_Night_10_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_11_en","features.messages.impl.timeline_TimelineView_Night_11_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_12_en","features.messages.impl.timeline_TimelineView_Night_12_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_13_en","features.messages.impl.timeline_TimelineView_Night_13_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_14_en","features.messages.impl.timeline_TimelineView_Night_14_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_15_en","features.messages.impl.timeline_TimelineView_Night_15_en",20563,], +["features.messages.impl.timeline_TimelineView_Day_16_en","features.messages.impl.timeline_TimelineView_Night_16_en",20563,], ["features.messages.impl.timeline_TimelineView_Day_17_en","features.messages.impl.timeline_TimelineView_Night_17_en",0,], -["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20553,], +["features.messages.impl.timeline_TimelineView_Day_1_en","features.messages.impl.timeline_TimelineView_Night_1_en",20563,], ["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",20553,], +["features.messages.impl.timeline_TimelineView_Day_4_en","features.messages.impl.timeline_TimelineView_Night_4_en",20563,], ["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",20553,], +["features.messages.impl.timeline_TimelineView_Day_6_en","features.messages.impl.timeline_TimelineView_Night_6_en",20563,], ["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",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20553,], -["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20553,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_0_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_0_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_1_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_1_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_2_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_2_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_3_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_3_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_4_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_4_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_5_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_5_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_6_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_6_en",20563,], +["libraries.troubleshoot.impl_TroubleshootNotificationsView_Day_7_en","libraries.troubleshoot.impl_TroubleshootNotificationsView_Night_7_en",20563,], ["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",20553,], -["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20553,], -["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20553,], -["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20553,], -["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20553,], -["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20553,], +["features.messages.impl.typing_TypingNotificationView_Day_1_en","features.messages.impl.typing_TypingNotificationView_Night_1_en",20563,], +["features.messages.impl.typing_TypingNotificationView_Day_2_en","features.messages.impl.typing_TypingNotificationView_Night_2_en",20563,], +["features.messages.impl.typing_TypingNotificationView_Day_3_en","features.messages.impl.typing_TypingNotificationView_Night_3_en",20563,], +["features.messages.impl.typing_TypingNotificationView_Day_4_en","features.messages.impl.typing_TypingNotificationView_Night_4_en",20563,], +["features.messages.impl.typing_TypingNotificationView_Day_5_en","features.messages.impl.typing_TypingNotificationView_Night_5_en",20563,], +["features.messages.impl.typing_TypingNotificationView_Day_6_en","features.messages.impl.typing_TypingNotificationView_Night_6_en",20563,], ["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","",20553,], +["libraries.matrix.ui.components_UnresolvedUserRow_en","",20563,], ["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",20553,], -["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20553,], -["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20553,], -["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20553,], +["features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Day_0_en","features.roomdetails.impl.notificationsettings_UserDefinedRoomNotificationSettingsView_Night_0_en",20563,], +["features.startchat.impl.components_UserListView_Day_0_en","features.startchat.impl.components_UserListView_Night_0_en",20563,], +["features.startchat.impl.components_UserListView_Day_1_en","features.startchat.impl.components_UserListView_Night_1_en",20563,], +["features.startchat.impl.components_UserListView_Day_2_en","features.startchat.impl.components_UserListView_Night_2_en",20563,], ["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",20553,], +["features.startchat.impl.components_UserListView_Day_7_en","features.startchat.impl.components_UserListView_Night_7_en",20563,], ["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",20553,], +["features.startchat.impl.components_UserListView_Day_9_en","features.startchat.impl.components_UserListView_Night_9_en",20563,], ["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.preferences.impl.user_UserPreferences_Day_2_en","features.preferences.impl.user_UserPreferences_Night_2_en",0,], -["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20553,], -["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20553,], -["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20553,], -["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20553,], -["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20553,], -["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20553,], -["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20553,], -["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20553,], -["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20553,], -["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20553,], -["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20553,], -["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20553,], -["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20553,], +["features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Day_0_en","features.userprofile.shared_UserProfileHeaderSectionWithVerificationViolation_Night_0_en",20563,], +["features.userprofile.shared_UserProfileHeaderSection_Day_0_en","features.userprofile.shared_UserProfileHeaderSection_Night_0_en",20563,], +["features.userprofile.shared_UserProfileMainActionsSection_Day_0_en","features.userprofile.shared_UserProfileMainActionsSection_Night_0_en",20563,], +["features.userprofile.shared_UserProfileView_Day_0_en","features.userprofile.shared_UserProfileView_Night_0_en",20563,], +["features.userprofile.shared_UserProfileView_Day_1_en","features.userprofile.shared_UserProfileView_Night_1_en",20563,], +["features.userprofile.shared_UserProfileView_Day_2_en","features.userprofile.shared_UserProfileView_Night_2_en",20563,], +["features.userprofile.shared_UserProfileView_Day_3_en","features.userprofile.shared_UserProfileView_Night_3_en",20563,], +["features.userprofile.shared_UserProfileView_Day_4_en","features.userprofile.shared_UserProfileView_Night_4_en",20563,], +["features.userprofile.shared_UserProfileView_Day_5_en","features.userprofile.shared_UserProfileView_Night_5_en",20563,], +["features.userprofile.shared_UserProfileView_Day_6_en","features.userprofile.shared_UserProfileView_Night_6_en",20563,], +["features.userprofile.shared_UserProfileView_Day_7_en","features.userprofile.shared_UserProfileView_Night_7_en",20563,], +["features.userprofile.shared_UserProfileView_Day_8_en","features.userprofile.shared_UserProfileView_Night_8_en",20563,], +["features.userprofile.shared_UserProfileView_Day_9_en","features.userprofile.shared_UserProfileView_Night_9_en",20563,], ["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",20553,], -["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20553,], +["features.preferences.impl.advanced_VideoQualitySelectorDialog_Day_0_en","features.preferences.impl.advanced_VideoQualitySelectorDialog_Night_0_en",20563,], +["features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Day_0_en","features.messages.impl.attachments.preview_VideoQualitySelectorDialog_Night_0_en",20563,], ["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",20553,], +["features.viewfolder.impl.file_ViewFileView_Day_3_en","features.viewfolder.impl.file_ViewFileView_Night_3_en",20563,], ["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/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_10_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_10_en.png index 8c6b1bd7cc..7281594c56 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Day_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d8ee76c2369a9671cbe370f367718fcda5bb08a89ed5116accc96928a64e9724 -size 55689 +oid sha256:c81c5e7e1a62ed5fc55d672de612c5ace83561f70a3e363ecc851a0ae3658b81 +size 54766 diff --git a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_10_en.png b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_10_en.png index 7983ef5e8a..c66df232c2 100644 --- a/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_10_en.png +++ b/tests/uitests/src/test/snapshots/images/features.invitepeople.impl_InvitePeopleView_Night_10_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21a24fade9819efdb9114ec0ba3db21ec87cf93e32d896e22117fcd4f23e07ce -size 53601 +oid sha256:d143c9fb43b79e3a6248b4eb179228b91652f43013da73d10fc5ec09384c20a9 +size 52486 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png index 4a5a13a36a..47145ebd49 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0ef35fd3f5346870f11120a37c9db969453b7594bf9a0ccc71fe43e7fdade488 -size 62532 +oid sha256:62df5826abbcd47bc2a18743f2baeef8c9c85ebc547660a9ae92328cd49499b0 +size 62768 diff --git a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en.png index 1b69f8f6a1..fa68b6c988 100644 --- a/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.login.impl.screens.classic.missingkeybackup_MissingKeyBackupView_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1501c2591f7df68404285770b1dad67360dddce074d4ce1c71223ea0baa0d1e4 -size 60873 +oid sha256:c92a6ada8c2aa5991c28935dafd8e35a0c0efc2c40660c16105b3cf381914cdd +size 61097 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png index 4a62c517f0..c98615fb74 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:712c1fca10ed7655634d300c03615c6c4dd2f71b74c178398d72fa0427f0d766 -size 41537 +oid sha256:1da26fc2ffe2216cda7aa1b6b92ba587c9d0bb56aa54586b3073befee96d29b6 +size 40956 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png index 3ee64a4d09..f4750d4a46 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da47d339d9b8712aa13c394482f8aa5d2e1fb4fcb8eb10df473394bfec1ef507 -size 25980 +oid sha256:da32161bd9a1fa8173d3f9713cab610500e5de95a369b3b57e0267db243b4705 +size 25418 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png index 4a56ec8135..9f15832109 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewDark_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:324ce7d935816d87fea7b70bc7ebaacb0ac1d007b08dba85f03c03a1f045e450 -size 36764 +oid sha256:1a4be2c70eb477dbd58e4e6924d0141f1c8d7205807d968b3a34221c12a301c6 +size 36176 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png index d2e319b028..ebe4511bdf 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c149288a8ef258f65292f673b9a15ea34910db6d3bfe2402b2a3264227f2b0d -size 42547 +oid sha256:6a0202d081e5aed85ca093239fae1c8f46d42fd6e859c818f5c0301597e5b473 +size 41957 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png index cdd9ef1a41..d90b4810bd 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_1_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ecf19446d8a0cf57431f13cbac9331ff72c93637c1cd1b442ed6330566debb2 -size 26879 +oid sha256:2dd256cb0782cc6ebbc3e432646b2d3abe92a72886311b4010b38d389703b939 +size 26329 diff --git a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png index a83adbff85..155302aafc 100644 --- a/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png +++ b/tests/uitests/src/test/snapshots/images/features.preferences.impl.root_PreferencesRootViewLight_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00c7c42f1e6dde16916ae12a889b728c0fb321aa2c3fc6af80ec01d99a3af7a6 -size 37164 +oid sha256:2ae20b874dba38a89a59e418bce33e748449446e0fc913b7f3ff2e87b8200c40 +size 36568 From 96cbe7664b3ebdba9ec28ce373e42e36637b638e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2026 19:20:26 +0200 Subject: [PATCH 44/44] Update dependencyAnalysis to v3.7.0 (#6616) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67cb3559b8..1adfc917ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -51,7 +51,7 @@ telephoto = "0.19.0" haze = "1.7.2" # Dependency analysis -dependencyAnalysis = "3.6.1" +dependencyAnalysis = "3.7.0" # DI metro = "0.13.2"